繁体   English   中英

从使用 state 更新后 State 不变

[英]State not changing after update from use state

我是反应新手。 我正在尝试使我的套接字 io 监听器工作。 当我使用它时useEffect可以工作,但它被调用了几次。 useEffect ,它只被调用一次(这显然很好),但这次users没有更新 - 初始值。

function Users() {
    const [users, setUsers] = useState([]);

    useEffect(() => {
        getUsers();

        if(users.length > 0) {
            socket.on("statusChange", (data) => {
                console.log(users); // this returns initial state of users
                let tempUsers = [...users];
                let ndx = tempUsers.findIndex(obj => obj.id === data.id);
                if(ndx === -1)
                    return;

                tempUsers[ndx].status = data.status;
                setUsers(tempUsers);
            });
        }
    }, []);

    function getUsers() {
        fetch(/* stuff */)
        .then(res => res.json())
        .then(res => setUsers(res.data));
    }

    return (
        <div className={styles.container}>
            <div className={styles.usersContainer}>
                { users.map((user, i) => <UserCard key={i} user={user} />) }
            </div>
        </div>
    );
}

export default Users;

我做出假设的一些部分:

  1. getUsers()应该只被调用一次:当组件挂载时
  2. 我们想监听socket.on("statusChange")并获取我们从getUsers()获得的用户的更新。
// This is pulled outside the component.
function getUsers() {
  fetch(/* stuff */)
  .then(res => res.json());
}

function Users() {
    const [users, setUsers] = useState([]);

    // Fetch users only once, when the component mounts.
    useEffect(() => {
      getUsers().then(res => {
        setUsers(res.data);
      });
    }, []);

    // Listen to changes
    useEffect(() => {
      if (!users.length) return;

      const listener = (data) => {
        // Functional update
        // See: https://reactjs.org/docs/hooks-reference.html#functional-updates
        setUsers(prevUsers => {
          let nextUsers = [...prevUsers];
          let ndx = nextUsers.findIndex(obj => obj.id === data.id);
          
          // What's up here? See below.
          if(ndx === -1) return nextUsers;

          nextUsers[ndx].status = data.status;
          return nextUsers;
        });
      };

      socket.on("statusChange", listener);

      // Unsubscribe when this component unmounts
      // See: https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1
      return () => socket.off("details", listener);
    }, [users]);

    return (
        <div className={styles.container}>
            <div className={styles.usersContainer}>
                { users.map((user, i) => <UserCard key={i} user={user} />) }
            </div>
        </div>
    );
}

export default Users;

关于if(ndx === -1) return nextUsers;

这意味着users的大小永远不会改变,即您不会处理有关新用户的数据。

或者,您可以执行if(ndx === -1) return [...nextUsers, data ];

与其简单地执行 getUsers,不如将其与回调一起使用。 然后在callBack中执行setUsers:

 function Users() { const [users, setUsers] = useState([]); useEffect(() => { fetch(/* stuff */).then(res => res.json()).then(res => { if(res.data.length > 0) { socket.on("statusChange", (data) => { console.log(res.data); // this returns initial state of users let tempUsers = [...res.data]; let ndx = tempUsers.findIndex(obj => obj.id === data.id); if(ndx === -1) return; tempUsers[ndx].status = data.status; setUsers(tempUsers); }); } }); }, []); return ( <div className={styles.container}> <div className={styles.usersContainer}> { users.map((user, i) => <UserCard key={i} user={user} />) } </div> </div> ); } export default Users;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM