轻松渲染优化:使用React Hooks进行state跟踪

轻松渲染优化:使用React Hooks进行state跟踪

轻松渲染优化:使用React Hooks进行state跟踪
做者 | Daishi Kato
译者 | 王文刚
编辑 | Yoniereact

介绍

React useContext 使用起来很是方便,它能够访问定义 DOM 树中多个组件的全局状态或共享状态。
可是,useContext 不是专为全局状态设计的,而且有一个警告:对上下文值的任何更改都会多播,致使全部 useContext 从新渲染组件。
这篇文章展现了一些关于问题的示例代码以及具备 state 使用跟踪的解决方案。git

问题定位

咱们以人为对象来举例说明。github

const initialState = {
  firstName: 'Harry',
  familyName: 'Potter',
};

咱们使用上下文和 local state。redux

const PersonContext = createContext(null);

const PersonProvider = ({ children }) => {
  const [person, setPerson] = useState(initialState);
  return (
    <PersonContext.Provider value={[person, setPerson]}>
      {children}
    </PersonContext.Provider>
  );
};

最后,这是一个显示人物名字的组件。ide

const DisplayFirstName = () => {
  const [person] = useContext(PersonContext);
  return (
    <div>First Name: {person.firstName}</div>
  );
};

到如今为止还挺好。
可是,问题是当你更新此人的 family name 的同时,它将触发 DisplayFirstName 从新渲染,甚至渲染结果都是相同的。
请注意,这是否是一个真正的问题,直到它成为一个问题。一般状况下,大多数较小的应用程序均可以正常运行,可是一些较大的应用程序会产生性能问题。性能

解决方案

让咱们看看状态使用跟踪如何解决这个问题。
provider 看起来有点不一样,但代码基本相同。优化

const usePerson = () => useState(initialState);
const { Provider, useTracked } = createContainer(usePerson);

const PersonProvider = ({ children }) => (
  <Provider>
    {children}
  </Provider>
);

DisplayFirstName 组件像这样更改。spa

const DisplayFirstName = () => {
  const [person] = useTracked();
  return (
    <div>First Name: {person.firstName}</div>
  );
};

注意这个变化?只有区别是 useTracked()而不是 useContext(...)。
经过这个小的更改,跟踪 DisplayFirstName 中的状态使用状况。如今,即便更新了 family name,只要 first name 未更新,该组件就不会从新渲染。
这是轻松的渲染优化。设计

高级示例

有些读者可能会认为也能够经过相似 useSelector 的 hooks API 来实现。
这是另外一个使用 useTracked 的例子。code

const initialState = {
  firstName: 'Harry',
  familyName: 'Potter',
  showFullName: false,
};

假设咱们有一个像上面这样的 state ,让咱们建立一个带有条件的组件。

const DisplayPersonName = () => {
  const [person] = useTracked();
  return (
    <div>
      {person.showFullName ? (
        <span>
          Full Name: {person.firstName}
          <Divider />
          {person.familyName}
        </span>
      ) : (
        <span>First Name: {person.firstName}</span>
      )}
    </div>
  );
};

此组件将在两个场景中从新渲染:
a)当更新 firstName 或 familyName 时,显示全名。
b)当更新 firstName 时,不显示全名。
使用 useSelector 重现相同的行为并不容易,最终可能会在组件中分开。

使用状态来进行跟踪的项目

有两个项目使用状态来跟踪:

  • reactive-react-redux:这是 react-redux 的替代库。它具备相同的 hooks API 和 useTrackedState hook。Github地址:

https://github.com/dai-shi/reactive-react-redux

结束

这篇文章重点介绍了如何轻松使用状态跟踪。篇幅限制,咱们并无讨论这些类库的具体实现。简而言之,咱们使用 Proxy API 来跟踪状态使用状况。咱们还在 Context API 中使用未记录的功能来中止广播。若是你对这些细节感兴趣,请查看如上所述的 GitHub 库。

相关文章
相关标签/搜索