【问题标题】:Update a "UseContext array" fail to re-render/generate a new component更新“UseContext 数组”无法重新渲染/生成新组件
【发布时间】:2021-08-20 10:28:37
【问题描述】:

使用上下文存储一个数组并尝试通过array.map生成一个组件列表,但是UI没有重新渲染来显示所有组件。

节目背景:

我有一个包含数组的上下文,并且 UI 将有一个“添加”按钮。

我的目标:

  1. 当用户按下“添加”时
  2. 上下文中的数组将被推送一个新值
  3. UI 将被重新渲染并生成一个新组件

我的问题:

我尝试使用 useState 来存储数组,这完全没问题,因为一旦我使用 setArray 更新列表,就会触发重新渲染并显示一个新组件。

但是,当我尝试使用 useContext 时,页面不会被重新渲染。

  1. 我还应该使用 useState 来执行我的目标吗? (然后我必须管理 2 个变量,即上下文和状态,我认为这是处理它的一种虚拟方式。)
  2. 还有其他方法可以实现我的目标吗?

这是沙盒演示: https://codesandbox.io/s/falling-field-ur748?file=/src/App2.js

【问题讨论】:

    标签: reactjs react-hooks react-context


    【解决方案1】:

    只有在上下文提供的value发生变化时,订阅上下文的组件才会重新渲染。

    在此处将值推送到列表中将不起作用,因为 list 数组的引用不会在您推送时更改。所以在这种情况下你应该使用状态和上下文的组合。

    维护状态中的列表并将其与状态更新器setList一起作为值传递给Provider。

    const [ list , setList ] = React.useState([121, 123])
    
      return (
        <UserContext.Provider value={[list, setList]}>
          <App2 />
        </UserContext.Provider>
      );
    

    现在从订阅上下文的组件更新状态。

    export default function App2() {
      const [list, setList] = useContext(UserContext);
      const buttonOnClick = () => {
          setList(prevList => [...prevList, 321])
      };
      return (
        <>
          <button onClick={buttonOnClick}>Add</button>
          {list.map((item) => (
            <p>{item}</p>
          ))}
        </>
      );
    }
    

    【讨论】:

    • 感谢您的解释。是否可以不将上下文对象更改为 useState 来实现目标?
    • 据我所知,我认为没有。您不仅希望上下文提供更新的值,而且您还需要重新渲染以渲染列表中的新项目。在 react 中触发重新渲染的唯一方法是更改​​状态或道具。
    • 让我回顾一下你的答案,看看我的理解是否正确。由于在上下文数组中推送新值不会更改引用。 React 不会考虑 state 或 props 的变化,因此不会重新渲染。所以,我必须同时使用 context 和 usestate 来执行任务
    • 是的,没错!由于引用检查,对数组或对象进行变异不是一个好习惯。
    • 非常感谢,伙计!你让我头疼不已:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 2020-05-06
    • 2018-06-15
    • 1970-01-01
    • 2018-08-12
    • 2019-06-01
    相关资源
    最近更新 更多