首页 > 解决方案 > 这是更新状态的正确方法吗?

问题描述

我的组件如下所示:

import cloneDeep from "clone-deep";
import { Context } from "../../context";

const Component = () => {
  const context = useContext(Context);
  const [state, setState] = useState(
    { 
      _id: "123", 
      users: [
        { 
          _id: "1",
          points: 5
        },
        {
          _id: "2",
          points: 8 
        }
      ]
    }
  );

  useEffect(() => {
    context.socket.emit("points");

    context.socket.on("points", (socketData) => {

          setState(prevState => {
    const newState = {...prevState};
    const index = newState.users
      .findIndex(user => user._id == socketData.content._id);
    newState.users[index].points = socketData.content.points;
    return newState;
  })
      
    });

    return () => context.socket.off("points");
  }, []);



  return <div>(There is table with identificators and points)</div>
};

我想知道这是否是正确的方法。我只想以正确的方式编写代码。或者使用深度克隆可能会更好?有关系吗?

setState(prevState => {
const newState = cloneDeep(prevState);
const index = newState.users
  .findIndex(user => user._id == "2");
newState.users[index].points++;
return newState;

})

编辑:我添加了其余代码以使其更易于理解。

标签: reactjsreact-hooks

解决方案


在您当前的代码中:

  useEffect(() => {
    setState((prevState) => {
      const newState = { ...prevState };
      const index = newState.users.findIndex((user) => user._id == "2");
      newState.users[index].points++;
      console.log({ prevState, newState });
      return newState;
    });
  }, []);

您可以看到它prevState正在发生变异(点数为 9):

    { 
      _id: "123", 
      users: [
        { 
          _id: "1",
          points: 5
        },
        {
          _id: "2",
          points: 9 // Mutated!
        }
      ]
    }

为了避免改变状态,你必须使用不改变的方法,例如扩展运算符或映射函数:

  useEffect(() => {
    setState((prevState) => {
      const newState = ({
        ...prevState,
        users: prevState.users.map((user) =>
          user._id === "2"
            ? {
                ...user,
                points: user.points + 1
              }
            : user
        )
      })
      console.log({ prevState, newState });
      return newState
      }
    );
  }, []);

现在您可以看到 prevState 没有发生突变:

    { 
      _id: "123", 
      users: [
        { 
          _id: "1",
          points: 5
        },
        {
          _id: "2",
          points: 8 // Not mutated :)
        }
      ]
    }

推荐阅读