useReducer 状态返回未定义(反应)

问题描述 投票:0回答:1

我的功能组件有一个 useReducer 状态,它有两个输入,输入值设置为状态对象,状态在第一次渲染时完美运行,但是当我更改输入时,网页崩溃并且控制台错误说无法读取未定义的值 这是代码:

import React from "react";
import { useReducer } from "react";
import Card from "../UI/Card-Wrap/Card";
const Login = () => {
  const reducer = (state, action) => {
    if (action.id === "username") {
      state.username = action.value;
    }

    if (action.id === "password") {
      state.password = action.value;
    }
  };

  const [state, dispatch] = useReducer(reducer, {
    username: "",
    password: "",
  });

  const onChangeHandler = (e) => {
    dispatch(e.target);
  };

  return (
    <div>
      <Card>
        <form action="#" className={Styles.form}>
          <p>Login</p>
          <div className={Styles.username}>
            <label htmlFor="username">Username</label>
            <input
              type="text"
              id="username"
              onChange={onChangeHandler}
              value={state.username}
            />
          </div>
          <div className={Styles.password}>
            <label htmlFor="password">Password</label>
            <input
              type="password"
              id="password"
              onChange={onChangeHandler}
              value={state.password}

            />
          </div>
          <button type="submit">Submit</button>
        </form>
      </Card>
    </div>
  );
};

export default Login;

我试图找到它在每个渲染器上发生的位置,显然每次我在 Reducer 函数中设置状态值时都会发生。

reactjs react-hooks components
1个回答
0
投票

问题发生是因为你的reducer函数没有返回新状态。

这会导致在您发送操作后状态为

undefined
,然后在输入
cannot read value of undefined
属性时引发
value
错误。

根据 React 文档

状态是只读的。不要修改状态中的任何对象或数组:

function reducer(state, action) {   switch (action.type) {
    case 'incremented_age': {
      // 🚩 Don't mutate an object in state like this:
      state.age = state.age + 1;
      return state;
    }

相反,总是从你的减速器返回新对象:

function reducer(state, action) {   switch (action.type) {
    case 'incremented_age': {
      // ✅ Instead, return a new object
      return {
        ...state,
        age: state.age + 1
      };
    }

请注意,除了返回状态,它应该是一个新对象。
您不应该更改当前状态对象中的值,因为 JS 中的对象被视为 references 并且通过返回相同的状态对象,React 不会重新渲染您的组件。

所以,问题的解决方案可以重写 reducer 函数如下:

  const reducer = (state, action) => {
    switch (action.id) {
      case "username":
        return {
          ...state,               // Spreads the current state into a new object
          username: action.value, // and changes only the desired value
        };
      case "password":
        return {
          ...state,
          password: action.value,
        };
      default:
        return { ...state };
    }
  };
© www.soinside.com 2019 - 2024. All rights reserved.