创建和使用 Context

Context(上下文)为应用提供了一个无需为组件指定props就可以在组件树中传递数据的方法。在典型的 React 应用中,数据都是通过props由父及子进行传递的。如果一些属性是许多组件都需要使用的,例如用户信息,那么使用props就会十分复杂。Context 就是为了解决这类数据的共享而存在的,其中保存的是相对组件树来说的全局数据。

Context 使用React.createContext(defaultValue)方法完成创建,并使用Context.Provider组件对组件树的根组件进行包裹。在其后的组件中,任何订阅了这个 Context 的组件,都会从距离自己最近的 Provider 处获取到当前 Context 的值。如果需要多个 Context,可以使用嵌套的方式包裹组件树的根组件。

在组件树中的子组件需要指定本组件的contextType,来将 Context 绑定到相应的 Provider 上,并从 Provider 中获得值。

import { createContext } from "react";

export type OnlineStates = {
  users: User[];
  updateUsers: (users: User[]) => void;
};

export const OnlineContext = createContext<OnlineStates>({
  users: [],
  updateUsers: () => {},
});

function App() {
  const [users, setUsers] = useState<User[]>([]);

  return (
    <OnlineContext.Provider value={{ users, updateUsers: setUsers }}>
      // 这里放置其他需要使用Context的组件。
    </OnlineContext.Provider>
  );
}

Tip

在定义Context的时候,一定要注意导出所定义的Context,这在未来使用这个Context的组件中要使用。

上面这个示例中的 Context 可以在其下的组件树部分中像下面这个示例中一样使用。

import { useContext } from "react";
import { OnlineContext, OnlineStates } from "./context-provider";

function States() {
  const { users, updateUsers } = useContext<OnlineStates>(OnlineContext);

  // 这里可以直接使用从Context中获取到的users和updateUsers。
}

从上面这个示例中可以看到,Context 中实际上是可以传递任何内容的。这个示例中就传递了一个useState返回的set函数,这在其下的组件中调用 Context 中提供的方法updateUsers()时,就可以直接更新 Context 中的users内容了,也就变相的实现了一个基于组件树 Context 的组件间通信。