fluidstate-react
Advanced tools
Comparing version
@@ -1,5 +0,2 @@ | ||
import { Api } from "fluidstate/api"; | ||
import { FunctionComponent } from "react"; | ||
export declare const createHOCApi: (api: Api) => { | ||
withFluidState: <P>(Component: FunctionComponent<P>) => FunctionComponent<P>; | ||
}; | ||
export declare const withFluidState: <P>(Component: FunctionComponent<P>) => FunctionComponent<P>; |
165
hoc.js
@@ -6,97 +6,94 @@ "use strict"; | ||
}); | ||
exports.createHOCApi = void 0; | ||
exports.withFluidState = void 0; | ||
var _react = require("react"); | ||
var _testCounter = require("./test-counter"); | ||
var _onceRef = require("./once-ref"); | ||
const createHOCApi = api => { | ||
const withFluidState = Component => { | ||
const FluidComponent = (...args) => { | ||
const argsRef = (0, _react.useRef)(args); | ||
argsRef.current = args; | ||
const data = (0, _onceRef.useOnceRef)(() => ({ | ||
isInitialized: false, | ||
isWithinRender: false, | ||
result: null | ||
})); | ||
const [, rerender] = (0, _react.useState)(Symbol()); | ||
const renderControl = (0, _onceRef.useOnceRef)(() => api.createEmptyObserved()); | ||
var _core = require("fluidstate/core"); | ||
var _fluidstate = require("fluidstate"); | ||
const withFluidState = Component => { | ||
const FluidComponent = (...args) => { | ||
const argsRef = (0, _react.useRef)(args); | ||
argsRef.current = args; | ||
const data = (0, _onceRef.useOnceRef)(() => ({ | ||
isInitialized: false, | ||
isWithinRender: false, | ||
result: null | ||
})); | ||
const [, rerender] = (0, _react.useState)(Symbol()); | ||
const renderControl = (0, _onceRef.useOnceRef)(() => (0, _core.createObserved)(null)); | ||
// We should only rerun component render within rendering context | ||
// and in a way that preserves hook order | ||
const effect = (0, _onceRef.useOnceRef)(() => { | ||
let dependencies = new Set(); | ||
const computed = api.createComputed(() => { | ||
// This subscribes to renderControl, which allows us | ||
// to rerun computed at the right time | ||
api.get(renderControl.current); | ||
if (data.current.isWithinRender) { | ||
data.current.result = Component(...argsRef.current); | ||
dependencies = new Set(computed.dependencies); | ||
// We should only rerun component render within rendering context | ||
// and in a way that preserves hook order | ||
const effect = (0, _onceRef.useOnceRef)(() => { | ||
let dependencies = new Set(); | ||
const computed = (0, _core.createComputed)(() => { | ||
// This subscribes to renderControl, which allows us | ||
// to rerun computed at the right time | ||
(0, _core.get)(renderControl.current); | ||
if (data.current.isWithinRender) { | ||
data.current.result = Component(...argsRef.current); | ||
dependencies = new Set(computed.dependencies); | ||
} else { | ||
// Getting dependencies to preserve the same dependency list | ||
for (const dependency of dependencies) { | ||
(0, _core.get)(dependency); | ||
} | ||
// When not within render context, we shouldn't rerun | ||
// Component render. Instead, we simply ask React to rerender | ||
if (data.current.isInitialized) { | ||
return true; | ||
} else { | ||
// Getting dependencies to preserve the same dependency list | ||
for (const dependency of dependencies) { | ||
api.get(dependency); | ||
} | ||
// When not within render context, we shouldn't rerun | ||
// Component render. Instead, we simply ask React to rerender | ||
if (data.current.isInitialized) { | ||
return true; | ||
} else { | ||
data.current.isInitialized = true; | ||
} | ||
data.current.isInitialized = true; | ||
} | ||
return false; | ||
}); | ||
const stopEffect = api.createEffect(() => api.get(computed), shouldRerender => { | ||
if (shouldRerender) { | ||
rerender(Symbol()); | ||
// @ts-ignore | ||
if (0 && _testCounter.testCounter.increaseCount) { | ||
_testCounter.testCounter.increaseCount(); | ||
} | ||
} | ||
return false; | ||
}); | ||
const stopReaction = (0, _core.createCoreReaction)(() => (0, _core.get)(computed), shouldRerender => { | ||
if (shouldRerender) { | ||
rerender(Symbol()); | ||
// @ts-ignore | ||
if (0 && _testCounter.testCounter.increaseCount) { | ||
_testCounter.testCounter.increaseCount(); | ||
} | ||
}); | ||
return { | ||
} | ||
}); | ||
return { | ||
computed, | ||
stopReaction | ||
}; | ||
}); | ||
(0, _react.useEffect)(() => { | ||
return () => { | ||
const { | ||
computed, | ||
stopEffect | ||
}; | ||
}); | ||
(0, _react.useEffect)(() => { | ||
return () => { | ||
const { | ||
computed, | ||
stopEffect | ||
} = effect.current; | ||
api.disableComputed(computed); | ||
stopEffect(); | ||
}; | ||
}, []); | ||
stopReaction | ||
} = effect.current; | ||
(0, _core.disableComputed)(computed); | ||
stopReaction(); | ||
}; | ||
}, []); | ||
// At this point, we should rerender Component, since we are in | ||
// the rendering context | ||
data.current.isWithinRender = true; | ||
api.notify(renderControl.current); | ||
api.triggerUpdate(); | ||
data.current.isWithinRender = false; | ||
return data.current.result; | ||
}; | ||
if (Component.contextTypes) { | ||
FluidComponent.contextTypes = Component.contextTypes; | ||
} | ||
if (Component.defaultProps) { | ||
FluidComponent.defaultProps = Component.defaultProps; | ||
} | ||
if (Component.propTypes) { | ||
FluidComponent.propTypes = Component.propTypes; | ||
} | ||
if (Component.displayName) { | ||
FluidComponent.displayName = `FluidComponent(${Component.displayName})`; | ||
} | ||
return FluidComponent; | ||
// At this point, we should rerender Component, since we are in | ||
// the rendering context | ||
data.current.isWithinRender = true; | ||
(0, _core.notify)(renderControl.current); | ||
(0, _fluidstate.triggerUpdate)(); | ||
data.current.isWithinRender = false; | ||
return data.current.result; | ||
}; | ||
return { | ||
withFluidState | ||
}; | ||
if (Component.contextTypes) { | ||
FluidComponent.contextTypes = Component.contextTypes; | ||
} | ||
if (Component.defaultProps) { | ||
FluidComponent.defaultProps = Component.defaultProps; | ||
} | ||
if (Component.propTypes) { | ||
FluidComponent.propTypes = Component.propTypes; | ||
} | ||
if (Component.displayName || Component.name) { | ||
FluidComponent.displayName = `FluidComponent(${Component.displayName || Component.name})`; | ||
} | ||
return FluidComponent; | ||
}; | ||
exports.createHOCApi = createHOCApi; | ||
exports.withFluidState = withFluidState; | ||
//# sourceMappingURL=hoc.js.map |
@@ -1,5 +0,1 @@ | ||
import { Api } from "fluidstate/api"; | ||
import { ReactiveApi } from "fluidstate/reactive-api"; | ||
export declare const createHooksApi: (api: Api, reactiveApi: ReactiveApi) => { | ||
useFluidState: <T>(getState: () => T, dependencyArray?: ReadonlyArray<unknown>) => T; | ||
}; | ||
export declare const useFluidState: <T>(getState: () => T, dependencyArray?: ReadonlyArray<unknown>) => T; |
87
hooks.js
@@ -6,58 +6,55 @@ "use strict"; | ||
}); | ||
exports.createHooksApi = void 0; | ||
exports.useFluidState = void 0; | ||
var _react = require("react"); | ||
var _testCounter = require("./test-counter"); | ||
var _onceRef = require("./once-ref"); | ||
const createHooksApi = (api, reactiveApi) => { | ||
const useFluidState = (getState, dependencyArray = []) => { | ||
const isWithinRender = (0, _react.useRef)(true); | ||
isWithinRender.current = true; | ||
var _core = require("fluidstate/core"); | ||
var _fluidstate = require("fluidstate"); | ||
const useFluidState = (getState, dependencyArray = []) => { | ||
const isWithinRender = (0, _react.useRef)(true); | ||
isWithinRender.current = true; | ||
// result is a holder for the value returned from getState | ||
const result = (0, _react.useRef)(null); | ||
const [, rerender] = (0, _react.useState)(Symbol()); | ||
// result is a holder for the value returned from getState | ||
const result = (0, _react.useRef)(null); | ||
const [, rerender] = (0, _react.useState)(Symbol()); | ||
// Since we put the get state under dependency array, it'll change when | ||
// dependency array is changed | ||
const getStateCallback = (0, _react.useCallback)(getState, dependencyArray); | ||
// Since we put the get state under dependency array, it'll change when | ||
// dependency array is changed | ||
const getStateCallback = (0, _react.useCallback)(getState, dependencyArray); | ||
// An observed for getState function which will be used in the effect | ||
const getStateObserved = (0, _onceRef.useOnceRef)(() => api.createObserved(getStateCallback)); | ||
const stopEffect = (0, _onceRef.useOnceRef)(() => reactiveApi.createEffect(() => api.get(getStateObserved.current)(), value => { | ||
result.current = value; | ||
// If the result is first initialized or happens due to dependency array change | ||
// during render, we do not need to rerender, but is rerendered upon other changes | ||
if (!isWithinRender.current) { | ||
rerender(Symbol()); | ||
// @ts-ignore | ||
if (0 && _testCounter.testCounter.increaseCount) { | ||
_testCounter.testCounter.increaseCount(); | ||
} | ||
// An observed for getState function which will be used in the effect | ||
const getStateObserved = (0, _onceRef.useOnceRef)(() => (0, _core.createObserved)(getStateCallback)); | ||
const stopReaction = (0, _onceRef.useOnceRef)(() => (0, _fluidstate.createReaction)(() => (0, _core.get)(getStateObserved.current)(), value => { | ||
result.current = value; | ||
// If the result is first initialized or happens due to dependency array change | ||
// during render, we do not need to rerender, but is rerendered upon other changes | ||
if (!isWithinRender.current) { | ||
rerender(Symbol()); | ||
// @ts-ignore | ||
if (0 && _testCounter.testCounter.increaseCount) { | ||
_testCounter.testCounter.increaseCount(); | ||
} | ||
})); | ||
} | ||
})); | ||
// The effect is stopped when component unmounts | ||
(0, _react.useEffect)(() => { | ||
return () => { | ||
stopEffect.current(); | ||
}; | ||
}, []); | ||
// The effect is stopped when component unmounts | ||
(0, _react.useEffect)(() => { | ||
return () => { | ||
stopReaction.current(); | ||
}; | ||
}, []); | ||
// Upon dependency array change, if the callback is different, it'll recalculate | ||
// the effect since it depends on it | ||
if (!getStateObserved.current.inert.equal(getStateCallback)) { | ||
api.set(getStateObserved.current, getStateCallback); | ||
api.get(getStateObserved.current); | ||
} | ||
isWithinRender.current = false; | ||
// Upon dependency array change, if the callback is different, it'll recalculate | ||
// the effect since it depends on it | ||
if (getStateObserved.current.value !== getStateCallback) { | ||
(0, _core.set)(getStateObserved.current, getStateCallback); | ||
(0, _core.get)(getStateObserved.current); | ||
} | ||
isWithinRender.current = false; | ||
// Returning the current value from getState since it'll be kept | ||
// up to date due to rerendering | ||
return result.current; | ||
}; | ||
return { | ||
useFluidState | ||
}; | ||
// Returning the current value from getState since it'll be kept | ||
// up to date due to rerendering | ||
return result.current; | ||
}; | ||
exports.createHooksApi = createHooksApi; | ||
exports.useFluidState = useFluidState; | ||
//# sourceMappingURL=hooks.js.map |
@@ -1,13 +0,4 @@ | ||
/// <reference types="react" /> | ||
import { createHooksApi } from "./hooks"; | ||
import { createHOCApi } from "./hoc"; | ||
export { createHooksApi }; | ||
export { createHOCApi }; | ||
declare const defaultHooksApi: { | ||
useFluidState: <T>(getState: () => T, dependencyArray?: readonly unknown[]) => T; | ||
}; | ||
declare const useFluidState: <T>(getState: () => T, dependencyArray?: readonly unknown[]) => T; | ||
declare const withFluidState: <P>(Component: import("react").FunctionComponent<P>) => import("react").FunctionComponent<P>; | ||
export { defaultHooksApi }; | ||
import { withFluidState } from "./hoc"; | ||
import { useFluidState } from "./hooks"; | ||
export { useFluidState }; | ||
export { withFluidState }; |
23
index.js
@@ -6,29 +6,16 @@ "use strict"; | ||
}); | ||
Object.defineProperty(exports, "createHOCApi", { | ||
Object.defineProperty(exports, "useFluidState", { | ||
enumerable: true, | ||
get: function () { | ||
return _hoc.createHOCApi; | ||
return _hooks.useFluidState; | ||
} | ||
}); | ||
Object.defineProperty(exports, "createHooksApi", { | ||
Object.defineProperty(exports, "withFluidState", { | ||
enumerable: true, | ||
get: function () { | ||
return _hooks.createHooksApi; | ||
return _hoc.withFluidState; | ||
} | ||
}); | ||
exports.withFluidState = exports.useFluidState = exports.defaultHooksApi = void 0; | ||
var _fluidstate = require("fluidstate"); | ||
var _hoc = require("./hoc"); | ||
var _hooks = require("./hooks"); | ||
var _hoc = require("./hoc"); | ||
const defaultHooksApi = (0, _hooks.createHooksApi)(_fluidstate.defaultApi, _fluidstate.defaultReactiveApi); | ||
exports.defaultHooksApi = defaultHooksApi; | ||
const defaultHOCApi = (0, _hoc.createHOCApi)(_fluidstate.defaultApi); | ||
const { | ||
useFluidState | ||
} = defaultHooksApi; | ||
exports.useFluidState = useFluidState; | ||
const { | ||
withFluidState | ||
} = defaultHOCApi; | ||
exports.withFluidState = withFluidState; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "fluidstate-react", | ||
"version": "0.0.17", | ||
"version": "0.0.18", | ||
"description": "Library for using fine-grained reactivity state management library fluidstate in React", | ||
@@ -34,3 +34,3 @@ "repository": "https://gitlab.com/fluidstate/fluidstate-react", | ||
"babel-plugin-source-map-support": "^2.2.0", | ||
"fluidstate": "^0.0.17", | ||
"fluidstate": "^0.0.18", | ||
"jest": "^29.4.1", | ||
@@ -45,3 +45,3 @@ "prettier": "^2.8.3", | ||
"peerDependencies": { | ||
"fluidstate": "^0.0.17", | ||
"fluidstate": "^0.0.18", | ||
"react": "^18.2.0" | ||
@@ -48,0 +48,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
34734
-6.98%227
-13.36%