反应useReducer,调度无法按预期运行

时间:2019-09-19 16:06:52

标签: reactjs

我正在尝试更新参数,然后在搜索功能中使用这些值。在我的代码中,调度不会按预期更新state.params。

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应该更新searchParams变量,然后在onClick方法中分派,使其可用于其余的应用程序。 我想念什么?

2 个答案:

答案 0 :(得分:1)

如评论中所述;您无法在调度后获得状态,因为调度是异步的,doesn't return anything

您可以添加一个useEffect,然后在state.params更改时在其中进行一些操作,将state.params的初始值设置为NONE,以便您可以跳过第一次state.params更改:

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;

答案 1 :(得分:0)

尝试使用action.payload.searchParams代替action.searchParams