繁体   English   中英

如何避免与 React 挂钩相关的范围界定问题

[英]How can I avoid scoping problems related to React hooks

问题

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

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

  1. 在钩定义一些状态s
  2. 进行异步调用以获取一些数据d并使用它来设置状态s
  3. 基于d进行后续调用,并使用它来更新s

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

我的半解

我已经能够使用一些东西来解决这个问题,一些东西往往有效:

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

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

翻译:博士

在 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;
  })
})

暂无
暂无

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

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