gpt4 book ai didi

javascript - 如何避免与 React hooks 相关的范围问题

转载 作者:行者123 更新时间:2023-11-28 14:09:04 26 4
gpt4 key购买 nike

问题

我有一个反复出现的问题,每当我尝试使用钩子(Hook)做任何远程复杂和异步的事情时,似乎都会发生这个问题。

导致问题的时间线是这样的:

  1. 在钩子(Hook)s中定义某种状态
  2. 进行异步调用以获取一些数据d并使用它来设置状态s
  3. 根据d进行后续调用,并用它来更新s

问题是在 3.;当我想更新状态 s 时,此时它就是 s 因为它是在定义函数的范围内定义的,即。它没有最新更新状态的概念,只知道函数定义时的状态。

我的半解决方案

我已经能够使用一些方法来解决这个问题,一些通常有效的方法:

  1. 非规范化状态(无论如何可能是个好主意),这样我们就可以尽可能避免更新状态中的现有项目
  2. 超时后运行更新;使用 setTimeout 强制更新在下一个渲染周期中发生
  3. 完全忘记使用状态钩子(Hook),从外部管理状态并将所有内容作为 props 传入

这些并不总是(或永远)是好的或理想的解决方案。我猜我在这里遗漏了一些基本的东西,但我无法在网上找到任何有关此问题的信息,而且我还没有从同事那里得到任何可行的建议。

TL:DR

React 函数组件体内定义的函数将以其当时可以访问的范围来定义。这并不总是最新的状态。我怎样才能解决这个问题?

<小时/>

一个任意的例子来演示我在说什么:

const getUsers = () => Promise.resolve({
1: {
name: 'Mr 1',
favouriteColour: null,
},
2: {
name: 'Ms 2',
favouriteColour: null,
},
});

const getFavouriteColorForUser = (id) => Promise.resolve({ id, color: Math.random() > 0.5 ? 'red' : 'blue' });


const App = () => {
const [users, setUsers] = React.useState({});

const handleClick = () => {
getUsers()
.then(data => {
setUsers(data);
return Promise.resolve(data);
})
.then(data => {
return Promise.all(Object.keys(data).map(getFavouriteColorForUser));
})
.then(data => {
const updatedUsers = {
...users,
...data.reduce(
(p, c) => ({
...p,
[c.id]: {
...users[c.id],
favouriteColor: c.color
},
}),
{}
)
};

console.log('users:');
console.dir(users);
console.log('color data:');
console.dir(data);
console.log('updatedUsers:');
console.dir(updatedUsers);

setUsers(updatedUsers);
})
}

return (
<div>
{Object.keys(users).map(k => users[k]).map(user => (
<div>{user.name}'s favourite colour is {user.favouriteColour}</div>
))}
<button onClick={handleClick}>Get Users</button>
</div>
);
}

ReactDOM.render(<App />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

最佳答案

setState 有一个变体,您可以向它传递一个函数。保证使用状态中的最新值调用该函数。您可以用它来计算您的下一个状态:

.then(data => {
setUsers(previousUsers => {
const updatedUsers = {
...previousUsers, // <--- using previousUsers, not users
...data.reduce(
(p, c) => ({
...p,
[c.id]: {
...previousUsers[c.id], // <--- using previousUsers, not users
favouriteColor: c.color
},
}), {})
};

return updatedUsers;
})
})

关于javascript - 如何避免与 React hooks 相关的范围问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60230141/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com