举例useContext性能低下的样例,同时推荐用什么方法改进

在React中,useContext 是一种非常方便的全局状态管理工具,它可以让我们在组件之间共享状态,而不需要通过层层传递 props。然而,当我们在一个大型的 React 应用中过度使用 useContext 时,可能会遇到性能问题。这是因为当一个 context 的值改变时,所有使用这个 context 的组件都会重新渲染,即使这个组件并不需要那个改变的值。

示例

举个例子,假设我们有一个全局的用户 context,它包含了用户的详细信息和一些设置:

const UserContext = React.createContext();

function App() {
  const [user, setUser] = useState({ name: 'John', age: 30, theme: 'dark' });

  const handleChangeName = () => {
    setUser({ ...user, name: 'AAA' });
  };
  return (
    <UserContext.Provider value={user}>
      <Profile />
      <Settings />
      <button onClick={handleChangeName}>Change Name</button>
    </UserContext.Provider>
  );
}

function Profile() {
  const user = useContext(UserContext);
  
  return <h1>Welcome, {user.name}!</h1>;
}

function Settings() {
  const user = useContext(UserContext);
  
  return <div>Your current theme is: {user.theme}</div>;
}

在这个例子中,Profile 和 Settings 组件都使用了 UserContext。如果用户的主题改变了,Profile 组件也会重新渲染,即使它并不需要知道主题的信息。

改进方法

一种改进方法是使用 React 的 useMemouseCallback钩子来避免不必要的重新渲染。我们可以为每一个需要共享的状态创建一个单独的 context,然后使用 useMemo useCallback 来确保只有当这个状态改变时,使用这个状态的组件才会重新渲染:

const NameContext = React.createContext();
const ThemeContext = React.createContext();

function App() {
  console.log('App');
  const [user, setUser] = useState({ name: 'John', age: 30, theme: 'dark' });

  const userName = useMemo(() => user.name, [user.name]);
  const userTheme = useMemo(() => user.theme, [user.theme]);

  const handleChangeName = useCallback(() => {
    setUser({ ...user, name: 'AAA' });
  }, [user]);

  return (
    <>
      <NameContext.Provider value={userName}>
        <ThemeContext.Provider value={userTheme}>
          <Profile />
          <Settings />
          <button onClick={handleChangeName}>Change Name</button>
        </ThemeContext.Provider>
      </NameContext.Provider>
    </>
  );
}
const Profile = React.memo(function Profile() {
  console.log('Profile');
  const name = useContext(NameContext);

  return <h1>Welcome, {name}!</h1>;
});

const Settings = React.memo(function Settings() {
  console.log('Settings');
  const theme = useContext(ThemeContext);

  return <h1>Your current theme is: {theme}</h1>;
});

这样,只有当相关的状态改变时,对应的组件才会重新渲染,从而提高了性能。

posted @ 2024-01-10 18:46  走,板砖去  阅读(39)  评论(0编辑  收藏  举报