簡體   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