Reputation: 41665
I use selector (don't have to) to retrieve the nextStep
I dispatch someAction and this can change nextStep
that I want to do, however the nextStep
doesn't get updated with the following code.
const App = (props) => {
const dispatch = useDispatch()
const nextStep = useSelector(getNextStep)
const handleSubmit = () => {
dispatch(someAction()) // this can change the nextStep
dispatch(gotoStep(nextStep)) // this nextStep is computed before someAction
}
}
export const getNextStep = (state) => {
let {step, stepList} = state.my_reduxer
let index = stepList.indexOf(step) // someAction changes stepList
let next_step = stepList[index + 1]
return next_step
}
How do I get the updated nextStep
for gotoStep
action?
-- Edit
I can think of something like the following but not sure if this guarantees the correct behavior
const App = (props) => {
const dispatch = useDispatch();
const nextStep = useSelector(getNextStep);
const [done, setDone] = useState(false);
const handleSubmit = () => {
dispatch(someAction()); // this can change the nextStep
setDone(true);
};
useEffect(() => {
if (done) {
dipatch(gotoStep(nextStep)); // nextStep is hopefully updated?
}
}, [done]);
};
Upvotes: 5
Views: 4810
Reputation: 41665
Thanks for the discussion @Dennis Vash !
I wasn't sure if your solution would solve the problem I asked in the comment
Here's my solution, I still don't have definitive documented answer, but feel safer with it. (and it seems to work)
const App = (props) => {
const dispatch = useDispatch();
const nextStep = useSelector(getNextStep);
const myStepDone = useSelector(getMyStep);
const handleSubmit = () => {
dispatch(someAction()); // this can change the nextStep
dispatch(updateMyStepDone()); // let's use redux state for done
};
useEffect(() => {
if (myStepDone) {
dipatch(gotoStep(nextStep)); // I hope actions I submitted in handleSubmit updates state simulateneously
}
}, [myStepDone]);
};
Upvotes: 0
Reputation: 53874
someAction
might changenextStep
or it might not change nextStep, and I want to advance tonextStep
after done is updated andnextStep
is possibly updated.
This code guarantee you advance next step only when done
changes and you don't get a staled value.
const App = () => {
const nextStep = useSelector(getNextStep);
const stepRef = useRef(nextStep);
const handleSubmit = () => {
dispatch(someAction());
setDone(true);
};
useEffect(() => {
if (done) {
dispatch(gotoStep(stepRef.current));
}
}, [done]);
useEffect(() => {
stepRef.current = nextStep;
}, [nextStep]);
};
Upvotes: 1
Reputation: 2877
what suppose to trigger your effect is nextStep
itself, because if you use done
state it's still not guaranteed that object was reduced already
useEffect(() => dipatch(gotoStep(nextStep)), [nextStep]);
in case that at init render you don't want this effect to run then use like follow
const [ isInit, setIsInit ] = useState(true)
useEffect(() => isInit ? setIsInit(false) : dipatch(gotoStep(nextStep)), [nextStep]);
and now your handleSubmit
function takes care only for dispatching
const handleSubmit = () => dispatch(someAction()); // this can change the nextStep
Upvotes: 0