Reputation: 661
I want to dispatch an action which depends on a previously set state in a functional component. What are my options?
<Buton
onPress={() => {
setState(state + 1);
dispatch(myAction(state));
}}
/>
Edit: For clarity, I mean that the dispatched state is dependent on state being set previously. In pseudo code:
async () => {
await setState(state + 1);
dispatch(myAction(state));
}
Upvotes: 1
Views: 7384
Reputation: 3656
The goal is to setState, and then call a function with the previousState as an argument. In order to do that, let's write a custom hook to encapsulate that goal.
Our custom hook will initialize a useState hook, and return state, and a custom wrapped setState method.
When the custom setState method is called with a callback argument, we will push that callback into an array and save it to a ref.
Next we write a useEffect hook that will be called after React has finished committing any state changes.
Inside our useEffect hook we will call each of the callbacks in our ref list passing the previousState and nextState as arguments.
After the callbacks are finished, we clear the callbacks list and save the currentState to the previousState ref.
useStateWithCallback.js
import React, { useState, useRef, useEffect } from 'react';
export const useStateWithCallback = (initialState) => {
const [state, setState] = useState(initialState);
const previousState = useRef(initialState);
const myCallbacksList = useRef([]);
const setStateWithCallback = (state, callback) => {
setState(state);
if (callback) {
myCallbackList.current.push(callback);
}
};
useEffect(() => {
myCallbacksList.current.forEach((callback) => callback(previousState.current, state));
myCallbacksList.current = [];
previousState.current = state;
}, [state]);
return [state, setStateWithCallback];
};
import React from 'react';
import { useStateWithCallback } from './useStateWithCallback';
const Example = (props) => {
const [state, setState] = useStateWithCallback();
const handlePress = () => {
setState(
(prevState) => prevState + 1,
(prevState, currentState) => dispatch(myaction(prevState))
);
};
return <Buton onPress={handlePress} />;
};
Upvotes: 0
Reputation: 64707
If you want to dispatch an action when state
changes (using the new value), you probably want to use useEffect
:
useEffect(() => {
dispatch(myAction(state))
}, [state])
<Buton
onPress={() => {
setState(state + 1);
}}
/>
Upvotes: 5