使用状态更新后状态不变
State not changing after update from use state
我是 React 新手。我正在尝试让我的套接字 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;
与其简单地执行 getUsers,不如将其与回调一起使用。然后在回调中执行 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;
我假设的部分内容:
getUsers()
应该只调用一次:当组件挂载时
- 我们想收听
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 ];
我是 React 新手。我正在尝试让我的套接字 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;
与其简单地执行 getUsers,不如将其与回调一起使用。然后在回调中执行 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;
我假设的部分内容:
getUsers()
应该只调用一次:当组件挂载时- 我们想收听
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 ];