fluidstate-react
Advanced tools
Comparing version
@@ -1,31 +0,6 @@ | ||
export type DeepPartial<T, DepthLimit extends number = 15, DepthTracker extends unknown[] = []> = DepthTracker["length"] extends DepthLimit ? T : T extends object ? T extends (...args: any[]) => any ? T : T extends (infer E)[] ? DeepPartial<E, DepthLimit, [...DepthTracker, unknown]>[] : T extends readonly (infer E)[] ? readonly DeepPartial<E, DepthLimit, [...DepthTracker, unknown]>[] : T extends [infer E1, infer E2, infer E3, infer E4, infer E5, infer E6] ? [ | ||
DeepPartial<E1, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E2, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E3, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E4, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E5, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E6, DepthLimit, [...DepthTracker, unknown]> | ||
] : T extends [infer E1, infer E2, infer E3, infer E4, infer E5] ? [ | ||
DeepPartial<E1, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E2, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E3, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E4, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E5, DepthLimit, [...DepthTracker, unknown]> | ||
] : T extends [infer E1, infer E2, infer E3, infer E4] ? [ | ||
DeepPartial<E1, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E2, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E3, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E4, DepthLimit, [...DepthTracker, unknown]> | ||
] : T extends [infer E1, infer E2, infer E3] ? [ | ||
DeepPartial<E1, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E2, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E3, DepthLimit, [...DepthTracker, unknown]> | ||
] : T extends [infer E1, infer E2] ? [ | ||
DeepPartial<E1, DepthLimit, [...DepthTracker, unknown]>, | ||
DeepPartial<E2, DepthLimit, [...DepthTracker, unknown]> | ||
] : T extends [infer E1] ? [DeepPartial<E1, DepthLimit, [...DepthTracker, unknown]>] : { | ||
[K in keyof T]?: DeepPartial<T[K], DepthLimit, [ | ||
...DepthTracker, | ||
unknown | ||
]>; | ||
} : T; | ||
type Increment<A extends number[]> = [...A, 0]; | ||
type PrimitiveType = string | number | boolean | undefined | null | symbol | bigint; | ||
export type DeepPartial<T, Depth extends number = 10, CurrentDepth extends number[] = []> = T extends PrimitiveType ? T : CurrentDepth["length"] extends Depth ? T : { | ||
[K in keyof T]?: DeepPartial<T[K], Depth, Increment<CurrentDepth>>; | ||
}; | ||
export {}; |
57
hoc.js
@@ -11,2 +11,5 @@ "use strict"; | ||
let reactiveObjectId = 1; | ||
const COMPUTED_CONFIG = { | ||
equals: () => false | ||
}; | ||
@@ -27,8 +30,6 @@ /** | ||
const data = (0, _onceRef.useOnceRef)(() => ({ | ||
reactionToRun: [], | ||
isWithinRender: true, | ||
result: null, | ||
shouldRender: false | ||
isInitial: true, | ||
isWithinRender: false, | ||
shouldRerender: false | ||
})); | ||
data.current.isWithinRender = true; | ||
const [, rerender] = (0, _react.useState)(Symbol()); | ||
@@ -39,13 +40,21 @@ const renderControl = (0, _onceRef.useOnceRef)(() => (0, _fluidstate.createAtom)(`withReactive(${Component.displayName || Component.name || "Unknown"})/renderControl@${reactiveObjectId}`)); | ||
// and in a way that preserves hook order | ||
const reaction = (0, _onceRef.useOnceRef)(() => (0, _fluidstate.createReaction)(() => { | ||
const computed = (0, _onceRef.useOnceRef)(() => (0, _fluidstate.createComputedAtom)(`withReactive(${Component.displayName || Component.name || "Unknown"})/computed@${reactiveObjectId}`, () => { | ||
renderControl.current.reportObserved(); | ||
if (data.current.shouldRender) { | ||
data.current.result = Component(...argsRef.current); | ||
if (data.current.isWithinRender) { | ||
return Component(...argsRef.current); | ||
} else { | ||
data.current.shouldRerender = true; | ||
} | ||
}, { | ||
scheduler: fn => { | ||
data.current.reactionToRun.push(fn); | ||
if (!data.current.isWithinRender) { | ||
return null; | ||
}, COMPUTED_CONFIG)); | ||
const reaction = (0, _onceRef.useOnceRef)(() => (0, _fluidstate.createReaction)(() => { | ||
computed.current.get(); | ||
if (data.current.isInitial) { | ||
return; | ||
} | ||
if (data.current.shouldRerender) { | ||
data.current.shouldRerender = false; | ||
(0, _fluidstate.untrack)(() => { | ||
rerender(Symbol()); | ||
} | ||
}); | ||
} | ||
@@ -58,23 +67,11 @@ })); | ||
}, []); | ||
// At this point, we should rerender Component, since we are in | ||
// the rendering context | ||
if (data.current.reactionToRun.length < 1) { | ||
renderControl.current.reportChanged(); | ||
} | ||
data.current.isWithinRender = true; | ||
renderControl.current.reportChanged(); | ||
try { | ||
data.current.shouldRender = false; | ||
data.current.reactionToRun.forEach((reactionToRun, i) => { | ||
// We should only render the component once | ||
if (i === data.current.reactionToRun.length - 1) { | ||
data.current.shouldRender = true; | ||
} | ||
reactionToRun(); | ||
}); | ||
data.current.shouldRender = false; | ||
return computed.current.get(); | ||
} finally { | ||
data.current.reactionToRun = []; | ||
data.current.isInitial = false; | ||
data.current.shouldRerender = false; | ||
data.current.isWithinRender = false; | ||
} | ||
return data.current.result; | ||
}; | ||
@@ -81,0 +78,0 @@ if (Component.displayName || Component.name) { |
55
hooks.js
@@ -26,7 +26,10 @@ "use strict"; | ||
const useReactive = (getState, dependencyArray = []) => { | ||
const isWithinRender = (0, _react.useRef)(true); | ||
isWithinRender.current = true; | ||
const data = (0, _onceRef.useOnceRef)(() => ({ | ||
isInitial: true, | ||
isWithinRender: false, | ||
shouldRerender: false | ||
})); | ||
data.current.isWithinRender = true; | ||
// result is a holder for the value returned from getState | ||
const result = (0, _react.useRef)(null); | ||
const [, rerender] = (0, _react.useState)(Symbol()); | ||
@@ -40,13 +43,32 @@ | ||
const getStateDetails = (0, _onceRef.useOnceRef)(() => ({ | ||
atom: (0, _fluidstate.createAtom)(`useReactive/getState@${reactiveObjectId++}`), | ||
atom: (0, _fluidstate.createAtom)(`useReactive/getStateDetails/atom@${reactiveObjectId++}`), | ||
callback: getStateCallback | ||
})); | ||
// Upon dependency array change, if the callback is different, it'll recalculate | ||
// the effect since it depends on it | ||
if (getStateDetails.current.callback !== getStateCallback) { | ||
getStateDetails.current.callback = getStateCallback; | ||
getStateDetails.current.atom.reportChanged(); | ||
} | ||
const computed = (0, _onceRef.useOnceRef)(() => (0, _fluidstate.createComputedAtom)(`useReactive/computed@${reactiveObjectId++}`, () => { | ||
getStateDetails.current.atom.reportObserved(); | ||
if (!data.current.isWithinRender) { | ||
data.current.shouldRerender = true; | ||
} | ||
return getStateDetails.current.callback(); | ||
})); | ||
const reaction = (0, _onceRef.useOnceRef)(() => (0, _fluidstate.createReaction)(() => { | ||
getStateDetails.current.atom.reportObserved(); | ||
result.current = getStateDetails.current.callback(); | ||
computed.current.get(); | ||
// 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()); | ||
if (data.current.isInitial) { | ||
return; | ||
} | ||
if (data.current.shouldRerender) { | ||
data.current.shouldRerender = false; | ||
(0, _fluidstate.untrack)(() => { | ||
rerender(Symbol()); | ||
}); | ||
} | ||
})); | ||
@@ -60,16 +82,11 @@ | ||
}, []); | ||
// Upon dependency array change, if the callback is different, it'll recalculate | ||
// the effect since it depends on it | ||
if (getStateDetails.current.callback !== getStateCallback) { | ||
getStateDetails.current.callback = getStateCallback; | ||
getStateDetails.current.atom.reportChanged(); | ||
try { | ||
return computed.current.get(); | ||
} finally { | ||
data.current.isInitial = false; | ||
data.current.isWithinRender = false; | ||
data.current.shouldRerender = false; | ||
} | ||
isWithinRender.current = false; | ||
// Returning the current value from getState since it'll be kept | ||
// up to date due to rerendering | ||
return result.current; | ||
}; | ||
exports.useReactive = useReactive; | ||
//# sourceMappingURL=hooks.js.map |
{ | ||
"name": "fluidstate-react", | ||
"version": "0.0.23", | ||
"version": "0.0.27", | ||
"description": "Library for using fine-grained reactivity state management library fluidstate in React", | ||
@@ -5,0 +5,0 @@ "repository": "https://gitlab.com/fluidstate/fluidstate-react", |
@@ -1,2 +0,2 @@ | ||
import { FunctionComponent, Provider, PropsWithChildren } from "react"; | ||
import { FunctionComponent, Provider, PropsWithChildren, Context } from "react"; | ||
import { DeepPartial } from "./deep-partial"; | ||
@@ -99,2 +99,4 @@ /** | ||
createState: (props: SetupProps) => State; | ||
/** React context containing the returned state. */ | ||
StateContext: Context<State>; | ||
}; | ||
@@ -101,0 +103,0 @@ /** |
@@ -149,3 +149,4 @@ "use strict"; | ||
MockProvider, | ||
createState | ||
createState, | ||
StateContext: StateContext | ||
}; | ||
@@ -152,0 +153,0 @@ }; |
@@ -350,2 +350,6 @@ # fluidstate-react | ||
#### `StateContext` | ||
The React Context object used by the Provider. | ||
#### Utility Types | ||
@@ -352,0 +356,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
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
361
1.12%0
-100%74600
-2.15%515
-1.34%