Dante Cervantes
Dante Cervantes

Reputation: 313

useReducer not updating correctly

I have a Select custom component, that only have a select, options and listen for a onChange, then i have a useReducer code, that initialize with some variables, after select one option my state still have the initialized value

When i select ANOTHER the value in performSearch is ALL

const reducer = (state, newState) => ({ ...state, ...newState });
const [state, setState] = useReducer(reducer, {
    filterStatus : 'ALL'
});

const performSearch = () => {
  console.log(state.filterStatus) //<= first time is ALL, second time same value ALL, third, is another value
}

useEffect(() => {
   performSearch()
},[])

<Select             
     onChange={(e) => {
        const {value} = e.target                
        setState({filterStatus:value})
        performSearch()            
      }}
      items={[{key:"ALL",value:"ALL"},{key:"ANOTHER",value:"ANOTHER"}]}
/>

any idea?

Upvotes: 0

Views: 584

Answers (2)

Steve K
Steve K

Reputation: 9045

If I had to guess I'd say that its because you are trying to call performSearch to log the console before the state is set. If you console log the state before you return your component you will probably be able to see the correct value in the state. I'm not sure what your use case is but if you want to use the value you can just return it in your function and not worry about the reducer and state at all. Like so:

const performSearch = (value) => {
  console.log(value)
}

useEffect(() => {
   performSearch('ALL')
},[])

<Select             
     onChange={(e) => {
        const {value} = e.target                
        performSearch(value)            
      }}
      items={[{key:"ALL",value:"ALL"},{key:"ANOTHER",value:"ANOTHER"}]}
/>

if you need to use the reducer then you can probably create a promise or I would just return the value to preformSearch and then set the state through your reducer from there like so:

const reducer = (state, newState) => ({ ...state, ...newState });
const [state, setState] = useReducer(reducer, {
    filterStatus : 'ALL'
});

const performSearch = (value) => {
  setState({filterStatus: value});

  //Do your stuff with the value
  console.log(value)
}

useEffect(() => {
   //you can probably just set the value in preformSearch here manually or you can set it to the states value but setting to the states value would result in another render because you would set the state in performSearch again
   performSearch(state.filterStatus)
},[])

<Select             
     onChange={(e) => {
        const {value} = e.target
        performSearch(value)            
      }}
      items={[{key:"ALL",value:"ALL"},{key:"ANOTHER",value:"ANOTHER"}]}
/>

But like I said I'm not really sure what your end goal is with this component but for this use case I'm not sure you need to use the useReducer function at all.

Upvotes: 1

German
German

Reputation: 557

The problem is that you are calling performSearch() inside the onChange function, so when you set the new state you will only see the value from the previous state. Try to put the performSearch function outside of the onSelect function and you will get the correct output.

Upvotes: 0

Related Questions