使用自定义useContext钩子消费React Context API并重新渲染

4

我刚开始学习Web开发并尝试使用React.js。

我开始探索Context API,其中我意识到当组件订阅了上下文并且上下文的值发生更改时,重新渲染(如果已挂载)/更新会发生。

因此,我尝试通过编写一些片段来理解情况,这里是完整的代码库。

在示例中,我创建了两个组件(BucketVegies.jsxBucketFruits.jsx),它们有一个共同的父组件(Fridge.jsx)

然后我创建了两个上下文 ContextVegies ContextFruits,并分别用它们自己的提供程序和使用者。 我使用自定义钩子(useVegiesContextuseFruitsContext)暴露了使用者。

我的问题是:

为什么兄弟组件在更改任何一个上下文的值时都会重新渲染?根据我所读的内容,只有订阅上下文的组件在其上下文值变化时才必须重新渲染/更新。(在我们的示例中,我们通过点击按钮来“添加”一个项目,因此值发生了更改)


1
尝试使用react-memo或类似的东西了吗?得到答案了吗?我尝试将提供程序分离到兄弟组件中,但不起作用。 - tanmoy
我没有进一步追求它,因为这更是一项优化活动,但我很乐意听取任何建议。 - odus-ex
1个回答

0
 const handleAddFruits = useCallback(() => {
    setFruits(fruits=>[...fruits, `Fruit${fruits.length + 1}`]);
  },[]);
  const handleAddVegies = useCallback(() => {
    setVegies(vegies=>[...vegies, `Vegie${vegies.length + 1}`]);
  },[]);
const vegiesValue=useMemo(()=>({ vegies, handleAddVegies }),[vegies,handleAddVegies])
const fruitsValue=useMemo(()=>({ fruits, handleAddFruits }),[fruits,handleAddFruits])
  return (
    <ContextVegies.Provider value={vegiesValue}>
      <ContextFruits.Provider value={fruitsValue}>
        {children}
      </ContextFruits.Provider>
    </ContextVegies.Provider>

这解决了在 FridgeContext 中的问题。

如果你想尝试这个库 react-context-slices,它可以让你快速轻松地处理上下文。你可以使用这个库来做到这一点:

// slices.js
import getHookAndProviderFromSlices from "react-context-slices"
export const {useSlice, Provider} = getHookAndProviderFromSlices({
  count: {initialArg: 0},
  // rest of slices of Context you want to define
})

// app.js
import {useSlice} from "./slices"
const App = () => {
  const [count, useCount] = useSlice("count")
  return <>
    <button onClick={() => setCount(c => c + 1)}>+</button>{count}
  </>
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接