New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useSteps(): only update setStep when needed #774
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { useCallback, useEffect, useState } from 'react' | ||
import { useCallback, useEffect, useReducer, useState } from 'react' | ||
import keycodes from './keycodes' | ||
import { log, removeStartingSlash } from './utils' | ||
|
||
|
@@ -41,32 +41,57 @@ export function useArrows({ onUp, onLeft, onDown, onRight } = {}) { | |
}, [onUp, onLeft, onDown, onRight]) | ||
} | ||
|
||
function stepsReducer(state, { type, value, steps }) { | ||
const { step } = state | ||
|
||
let newStep = null | ||
|
||
if (type === 'set') { | ||
newStep = value | ||
} | ||
if (type === 'next' && step < steps - 1) { | ||
newStep = step + 1 | ||
} | ||
if (type === 'prev' && step > 0) { | ||
newStep = step - 1 | ||
} | ||
|
||
if (newStep !== null && step !== newStep) { | ||
return { | ||
step: newStep, | ||
direction: newStep > step ? 1 : -1, | ||
} | ||
} | ||
|
||
return state | ||
} | ||
|
||
// Simple hook to manage a given number of steps. | ||
export function useSteps(steps) { | ||
const [step, _setStep] = useState(0) | ||
const [direction, setDirection] = useState(0) | ||
const [{ step, direction }, updateStep] = useReducer(stepsReducer, { | ||
step: 0, | ||
direction: 0, | ||
}) | ||
|
||
// If the number of steps change, we reset the current step | ||
useEffect(() => { | ||
updateStep({ type: 'set', value: 0, steps }) | ||
}, [steps]) | ||
|
||
const setStep = useCallback( | ||
newStep => { | ||
if (step !== newStep) { | ||
setDirection(newStep > step ? 1 : -1) | ||
_setStep(newStep) | ||
} | ||
value => { | ||
updateStep({ type: 'set', value, steps }) | ||
}, | ||
[setDirection, _setStep, step] | ||
[steps] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we not need to include the reducer's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exactly, [1] Search for “guarantees” in these two sections: https://reactjs.org/docs/hooks-reference.html#usestate |
||
) | ||
|
||
const next = useCallback(() => { | ||
if (step < steps - 1) { | ||
setStep(step + 1) | ||
} | ||
}, [setStep, step, steps]) | ||
updateStep({ type: 'next', steps }) | ||
}, [steps]) | ||
|
||
const prev = useCallback(() => { | ||
if (step > 0) { | ||
setStep(step - 1) | ||
} | ||
}, [setStep, step]) | ||
updateStep({ type: 'prev', steps }) | ||
}, [steps]) | ||
|
||
return { | ||
direction, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to avoid making this change until after #768 was merged, so we don't have too many conflicts :).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverted :+1: