Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React useReducer, dispatch not working as intended

Tags:

reactjs

I'm trying to update params then using those values in a search function. In my code, the dispatch does not update the state.params as intended.

import React, { useReducer } from 'react'

const SearchForm = () => {
    let searchParams = {}
    const initialState = {
        params: {}
    }

    const reducer = (state, action) => {
        switch (action.type) {
            case 'UPDATE':
                return {
                    ...state,
                    params: action.searchParams
                }
            default:
                return state
        }
    }
    const [state, dispatch] = useReducer(reducer, initialState)
    const handleChange = (e) => {
        const { name, value } = e.target

        searchParams = { ...searchParams, [name]: value }
    }

    const handleClick = () => {
        searchParams = { ...searchParams }
        console.log('SearchParams: ', searchParams)

        dispatch({ type: 'UPDATE', searchParams })
        // state.params returns nothing here
        console.log('Handle Click Dispatch: ', state.params)
    }

    return (
        <div>
            <select name="gender" onChange={handleChange}>
                <option value="">-- Choose --</option>
                <option value="Male">Male</option>
                <option value="Female">Female</option>
            </select><br />
            <select name="ethnicity" onChange={handleChange}>
                <option value="">-- Choose --</option>
                <option value="African-American">African American</option>
                <option value="Caucasian">Caucasian</option>
                <option value="Hispanic">Hispanic</option>
            </select><br />
            <button type="submit" onClick={handleClick}>Submit</button>
        </div>
    )
}
export default SearchForm

handleChange should update the searchParams variable then dispatch in the onClick method making it available for the rest of the app. What am I missing?

like image 599
user3831527 Avatar asked Dec 14 '25 05:12

user3831527


1 Answers

As stated in the comment; you cannot get the state after a dispatch because dispatch is asynchronous and doesn't return anything.

You could add a useEffect and do something there when state.params changed, set initial value of state.params to NONE so you can skip the first time state.params changed:

import React, {
  useReducer,
  useState,
  useEffect,
  useCallback,
} from 'react';
const NONE = {};
const initialState = {
  params: NONE,
};
const reducer = (state, action) => {
  switch (action.type) {
    case 'UPDATE':
      console.log('in reducer:', action.params);
      return {
        ...state,
        params: action.params,
      };
    default:
      return state;
  }
};

const SearchForm = () => {
  const [searchParams, setSearchParams] = useState({});

  const [state, dispatch] = useReducer(
    reducer,
    initialState
  );
  const handleChange = useCallback(
    e => {
      const { name, value } = e.target;

      setSearchParams({ ...searchParams, [name]: value });
    },
    [searchParams]
  );

  const handleClick = useCallback(() => {
    console.log('SearchParams: ', searchParams);

    dispatch({ type: 'UPDATE', params: searchParams });
  }, [searchParams]);
  const { params: stateParams } = state;
  useEffect(() => {
    if (stateParams !== NONE) {
      console.log('params in state changed: ', stateParams);
    }
  }, [stateParams]);

  return (
    <div>
      <select name="gender" onChange={handleChange}>
        <option value="">-- Choose --</option>
        <option value="Male">Male</option>
        <option value="Female">Female</option>
      </select>
      <br />
      <select name="ethnicity" onChange={handleChange}>
        <option value="">-- Choose --</option>
        <option value="African-American">
          African American
        </option>
        <option value="Caucasian">Caucasian</option>
        <option value="Hispanic">Hispanic</option>
      </select>
      <br />
      <button type="submit" onClick={handleClick}>
        Submit
      </button>
    </div>
  );
};
export default SearchForm;
like image 66
HMR Avatar answered Dec 16 '25 20:12

HMR



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!