Skip to content

Commit 4e557aa

Browse files
authored
Refactor/remove unused dispatcher code and implement useCallback (#42)
* Remove unnecessary isReRender flag We can derive this from workInProgressHook.queue and in useReducer we keep an update queue anyway. * Remove unnecessary guard in useMemo * Implement guaranteed useCallback hook Previously useCallback was a noop, however this leads to confusing situations where people rely on useCallback being a stable reference. * Replace useCallback with useMemo impl
1 parent 3eee22b commit 4e557aa

File tree

2 files changed

+13
-37
lines changed

2 files changed

+13
-37
lines changed

src/internals/__tests__/dispatcher.test.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,6 @@ describe('useEffect', () => {
2323
})
2424
})
2525

26-
describe('useCallback', () => {
27-
it('is an identity function', () => {
28-
const fn = () => {}
29-
expect(Dispatcher.useCallback(fn)).toBe(fn)
30-
})
31-
})
32-
3326
describe('useTransition', () => {
3427
it('returns noop and false', () => {
3528
const result = Dispatcher.useTransition()

src/internals/dispatcher.js

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ export const getCurrentIdentity = (): Identity => {
4040

4141
let firstWorkInProgressHook: Hook | null = null
4242
let workInProgressHook: Hook | null = null
43-
// Whether the work-in-progress hook is a re-rendered hook
44-
let isReRender: boolean = false
4543
// Whether an update was scheduled during the currently executing render pass.
4644
let didScheduleRenderPhaseUpdate: boolean = false
4745
// Lazily created map of render-phase updates
@@ -62,14 +60,10 @@ function areHookInputsEqual(
6260
) {
6361
// NOTE: The warnings that are used in ReactPartialRendererHooks are obsolete
6462
// in a prepass, since these issues will be caught by a subsequent renderer anyway
65-
if (prevDeps === null) {
66-
return false
67-
}
63+
if (prevDeps === null) return false
6864

6965
for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) {
70-
if (!is(nextDeps[i], prevDeps[i])) {
71-
return false
72-
}
66+
if (!is(nextDeps[i], prevDeps[i])) return false
7367
}
7468

7569
return true
@@ -87,25 +81,20 @@ function createWorkInProgressHook(): Hook {
8781
if (workInProgressHook === null) {
8882
// This is the first hook in the list
8983
if (firstWorkInProgressHook === null) {
90-
isReRender = false
91-
firstWorkInProgressHook = workInProgressHook = createHook()
84+
return (firstWorkInProgressHook = workInProgressHook = createHook())
9285
} else {
9386
// There's already a work-in-progress. Reuse it.
94-
isReRender = true
95-
workInProgressHook = firstWorkInProgressHook
87+
return (workInProgressHook = firstWorkInProgressHook)
9688
}
9789
} else {
9890
if (workInProgressHook.next === null) {
99-
isReRender = false
10091
// Append to the end of the list
101-
workInProgressHook = workInProgressHook.next = createHook()
92+
return (workInProgressHook = workInProgressHook.next = createHook())
10293
} else {
10394
// There's already a work-in-progress. Reuse it.
104-
isReRender = true
105-
workInProgressHook = workInProgressHook.next
95+
return (workInProgressHook = workInProgressHook.next)
10696
}
10797
}
108-
return workInProgressHook
10998
}
11099

111100
export function renderWithHooks(
@@ -200,7 +189,7 @@ function useReducer<S, I, A>(
200189
const dispatch: Dispatch<A> =
201190
queue.dispatch || (queue.dispatch = dispatchAction.bind(null, id, queue))
202191

203-
if (isReRender && renderPhaseUpdates !== null) {
192+
if (renderPhaseUpdates !== null) {
204193
// This is a re-render. Apply the new render phase updates to the previous
205194
// current hook.
206195
// Render phase updates are stored in a map of queue -> linked list
@@ -230,16 +219,11 @@ function useMemo<T>(nextCreate: () => T, deps: Array<mixed> | void | null): T {
230219
workInProgressHook = createWorkInProgressHook()
231220

232221
const nextDeps = deps === undefined ? null : deps
233-
234-
if (workInProgressHook !== null) {
235-
const prevState = workInProgressHook.memoizedState
236-
if (prevState !== null) {
237-
if (nextDeps !== null) {
238-
const prevDeps = prevState[1]
239-
if (areHookInputsEqual(nextDeps, prevDeps)) {
240-
return prevState[0]
241-
}
242-
}
222+
const prevState = workInProgressHook.memoizedState
223+
if (prevState !== null && nextDeps !== null) {
224+
const prevDeps = prevState[1]
225+
if (areHookInputsEqual(nextDeps, prevDeps)) {
226+
return prevState[0]
243227
}
244228
}
245229

@@ -297,8 +281,7 @@ function dispatchAction<A>(
297281
}
298282

299283
function useCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
300-
// Callbacks are passed as they are in the server environment.
301-
return callback
284+
return useMemo(() => callback, deps)
302285
}
303286

304287
function noop(): void {}

0 commit comments

Comments
 (0)