In react, with useState, I can pass it an updater function to get the current state within the same function. Currently I update a state multiple times within the same function.
Is that possible with a reducer dispatch with useReducer?
Thanks.
const someFunc = () => {
// some other computation
const result = someOtherFunc();
setState((state)=>{
// do something with current state
return {...state, result}
})
const result2 = someOtherFunc2();
setState((state)=>{
// do something with current state
return {...state, result2}
})
}
CodePudding user response:
Yes it is. You can do this by grouping all your states in like an initialState variable:
import { useReducer, useEffect } from 'react';
const SampleComponent = () => {
const reducer = (state, action) => ({...state, ...action})
const initialState = {
someName: '',
someCounter: 0,
isLoading: false
}
const [{
someName, someCounter, isLoading
}, dispatch ] = useReducer(reducer, initialState )
useEffect(() => {
dispatch({ isLoading: true }
const res = await fetch('https://someapi')
const json = await res.json()
if (json) {
dispatch({
someName: json.someNameValue,
someCounter: someCounter json.someCounterValue,
isLoading: false
})
}
}, [])
return (
<>
<h1>{someName}</h1>
<span>{someCounter}</span>
</>
)
}
There maybe other ways to do this, but the way works best for me is to:
Declare a reducer:
const reducer = (state, action) => ({...state, action})
Declare all states group in an object state:
const initialState = { someState: '' }
Use useReducer with the state variables and dispatch encapsulated with it:
const [{ someState }, dispatch ] = useReducer(reducer, initialState)
Use dispatch() method to set new values of states:
dispatch({ someState: newValue })
where newValue is any value you want to assign to someState.
CodePudding user response:
Yes it is possible. Whatever that can be done with useState
can also be done by useReducer
. It is the context that makes us decide on which to use.
Suppose I just want to update my loading state, then useState
is enough
const [isLoading, setIsLoading] = useState(true);
But let's suppose I have a input form, if I decide to useState, then it will be kind of like this
const [name, setName] = useState('')
const [age, setAge] = useState(0);
const [address, setAddress] = useState('');
instead of using all these useState
, I could directly using useReducer
for this specific application
const initialFormValues = {
name: '',
age: 0,
address: '',
};
const reducer = (state, action) =>{
switch(action.type) {
case "NAME": return { ...state, name: action.value};
case "AGE": return { ...state, age: action.value};
case "ADDRESS": return { ...state, address: action.value};
}
}
const [formValues, dispatch] = useReducer(reducer, initialFormValues);
Now whenever you want to update your input fields in the form, just use dispatch.
Both can do the task. Depending upon the use-case, we can choose the more appropriate one.