首页 > 解决方案 > React Context API 很慢

问题描述

我正在试验新的 Context API 和钩子。我创建了一个带有侧边栏(树视图)、页脚和主要内容页面的应用程序。我有一个上下文提供者

const ContextProvider: FunctionComponent = (props) => {

const [selected, setSelected] = useState(undefined);
const [treeNodes, setTreeNodes] = useState([]);

return (
    <MyContext.Provider
        value={{
            actions: {
                setSelected,
                setTreeNodes
            },
            selected,
            treeNodes
        }}
    >
        {props.children}
    </MyContext.Provider>
);

我是我的内容组件,我有一个包含大约 1000 个项目的 DetailsList(Office Fabric UI)。当我单击列表中的项目时,我想在上下文中更新所选项目。这有效,但它真的很慢。选择列表中的项目大约需要 0,5-1 秒。该列表是虚拟化的。我已经在生产版本中尝试过。事情要好一些,但点击列表时有明显的滞后。页脚正在使用 myContext 来显示有关所选项目的信息。

这是我的组件中的一些代码

const cntx = useContext(MyContext);

const onClick = (item) => {
    cntx.actions.setSelected(item);
};

我是否使用错误的上下文?

我创建了一个示例沙箱来演示。您可以滚动到大约 100 个索引并单击几次以查看它是如何变得无响应的。

https://codesandbox.io/s/0m4nqxp4m0

这是 Fabric DetailsList 的问题吗?它会重新渲染多次吗?我相信问题出在“复杂”的 DatePicker 组件上,但我不明白为什么会重新渲染 DetailsList?它没有在渲染函数中使用任何上下文属性。我希望只有页脚组件在每次上下文更改时重新呈现

标签: reactjsoffice-ui-fabricreact-hooksreact-context

解决方案


警告 因为上下文使用引用标识来确定何时重新渲染,所以当提供者的父级重新渲染时,有一些陷阱可能会触发消费者的无意渲染。例如,下面的代码将在每次 Provider 重新渲染时重新渲染所有消费者,因为总是为 value 创建一个新对象:

class App extends React.Component {
  render() {
    return (
      <Provider value={{something: 'something'}}>
        <Toolbar />
      </Provider>
    );
  }
}
To get around this, lift the value into the parent’s state:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: {something: 'something'},
    };
  }

  render() {
    return (
      <Provider value={this.state.value}>
        <Toolbar />
      </Provider>
    );
  }
}

https://reactjs.org/docs/context.html#caveats


推荐阅读