MCPcopy
hub / github.com/preactjs/preact / useReducer

Function useReducer

hooks/src/index.js:182–268  ·  view source on GitHub ↗
(reducer, initialState, init)

Source from the content-addressed store, hash-verified

180 * @returns {[ S, (state: S) => void ]}
181 */
182export function useReducer(reducer, initialState, init) {
183 /** @type {import('./internal').ReducerHookState} */
184 const hookState = getHookState(currentIndex++, 2);
185 hookState._reducer = reducer;
186 if (!hookState._component) {
187 hookState._value = [
188 !init ? invokeOrReturn(undefined, initialState) : init(initialState),
189
190 action => {
191 const currentValue = hookState._nextValue
192 ? hookState._nextValue[0]
193 : hookState._value[0];
194 const nextValue = hookState._reducer(currentValue, action);
195
196 if (currentValue !== nextValue) {
197 hookState._nextValue = [nextValue, hookState._value[1]];
198 hookState._component.setState({});
199 }
200 }
201 ];
202
203 hookState._component = currentComponent;
204
205 if (!currentComponent._hasScuFromHooks) {
206 currentComponent._hasScuFromHooks = true;
207 let prevScu = currentComponent.shouldComponentUpdate;
208 const prevCWU = currentComponent.componentWillUpdate;
209
210 // If we're dealing with a forced update `shouldComponentUpdate` will
211 // not be called. But we use that to update the hook values, so we
212 // need to call it.
213 currentComponent.componentWillUpdate = function (p, s, c) {
214 if (this._force) {
215 let tmp = prevScu;
216 // Clear to avoid other sCU hooks from being called
217 prevScu = undefined;
218 updateHookState(p, s, c);
219 prevScu = tmp;
220 }
221
222 if (prevCWU) prevCWU.call(this, p, s, c);
223 };
224
225 // This SCU has the purpose of bailing out after repeated updates
226 // to stateful hooks.
227 // we store the next value in _nextValue[0] and keep doing that for all
228 // state setters, if we have next states and
229 // all next states within a component end up being equal to their original state
230 // we are safe to bail out for this specific component.
231 /**
232 *
233 * @type {import('./internal').Component["shouldComponentUpdate"]}
234 */
235 // @ts-ignore - We don't use TS to downtranspile
236 // eslint-disable-next-line no-inner-declarations
237 function updateHookState(p, s, c) {
238 if (!hookState._component.__hooks) return true;
239

Callers 8

WidgetFunction · 0.90
StatefulFunction · 0.90
AppFunction · 0.90
CompFunction · 0.90
ReducerComponentFunction · 0.90
AbstractionFunction · 0.90
CompFunction · 0.90
useStateFunction · 0.85

Calls 5

getHookStateFunction · 0.85
invokeOrReturnFunction · 0.85
updateHookStateFunction · 0.85
setStateMethod · 0.80
initFunction · 0.50

Tested by 7

WidgetFunction · 0.72
StatefulFunction · 0.72
AppFunction · 0.72
CompFunction · 0.72
ReducerComponentFunction · 0.72
AbstractionFunction · 0.72
CompFunction · 0.72

Used in the wild real call sites across dependent graphs

searching dependent graphs…