According to React docs :
useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.
1. can somebody explain me why useReducer is not updating the state synchronously ?
const reducer = (state, action) => {
if( action.type === 'ADD_VALUE') {
console.log(`STATE IN REDUCER`, [...state, action.path]) // => ["1.1"]
return [...state, action.path]
}
}
const [state, dispatch] = useReducer(reducer, [])
<input type="button" onClick={() => {
dispatch({ type: 'ADD_VALUE', path: "1.1"})
console.log(`STATE`, state) // => []
// here i want to do some stuff based on the lastest updated state (["1.1"] and not [])
// for example dispatch an action with redux
}}/>
2. How can I do some stuff (dispatch a redux action) based on the lastest updated state (["1.1"] and not []) ?
Use useEffect to access the state correctly. You could add some safe-guarding if you want something invoking if a certain criterion is hit.
If you want to access your reducer across components, you can store the reducer using Context API. Look below for an example. You can see the reducer being injected into the Context on the parent component and then two child components that a) dispatches an action b) receives the update from the action.
1. Example of context reducer to use across multiple components
import React from "react";
import ReactDOM from "react-dom";
const Application = React.createContext({
state: null,
dispatch: null
});
function ActionComponent() {
const { dispatch } = React.useContext(Application);
return (
<div>
<div>Action Component</div>
<button onClick={() => dispatch("lol")}>Do something</button>
</div>
);
}
function ListenerComponent() {
const { state } = React.useContext(Application);
React.useEffect(
() => {
console.log(state);
},
[state]
);
return <div>Listener Component</div>;
}
function App() {
const [state, dispatch] = React.useReducer(function(state = [], action) {
return [...state, action];
});
return (
<Application.Provider value={{ state, dispatch }}>
<div className="App">
<ActionComponent />
<ListenerComponent />
</div>
</Application.Provider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
2. Example of local reducer without using Application Context
const reducer = (state, action) => {
if( action.type === 'ADD_VALUE') {
return [...state, action.path]
}
}
const [state, dispatch] = useReducer(reducer, [])
React.useEffect(() => {
console.log(state);
}, [state]);
<input type="button" onClick={() => {
dispatch({ type: 'ADD_VALUE', path: "1.1"})
}}/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With