React hooks之useContext

1,202 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第22天,点击查看活动详情

useContext 相当于 class 组件中的 static contextType = Context 或者 <Context.Consumer>, 它写起来比较方便,像是在this.props取值一样,一行代码就可以完成。它接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context的值由上层组件中距离当前组件最近的 <Context.Provider> 的 value 属性决定的。当上层组件提供的value属性发送变化,useContext会让当前组件重新渲染。

使用

一般我们项目开发中定义的全局信息可以放到context中,比如主题还有统一的样式前缀名称等等,还有也可以作为组件间状态传递使用,实现数据共享, 我们可以吧context看作为React 组件中类似的全局变量的形式。

语法类型定义

// 语法类型定义
interface Context<T> {
  Provider: Provider<T>;
  Consumer: Consumer<T>;
  displayName?: string | undefined;
}
function useContext<T>(context: Context<T>): T;

使用useContext前必须有定义好的context对象,要让其作为useContext的参数使用, 并且在使用useContext的上层某个组件使用了ConfigContext.Provider传递context的值,如果没有提供值则默认会使用createContext定义时定义的值。当Provider中的value发生变化后所有使用useContext的组件都能获取到最新的value值

interface ConfigContextProps {
  prefix: string
};

const ConfigContext = React.createContext<ConfigContextProps>({ prefix: 'ant' });

const Demo: React.FC = () => {
  return (
    <ConfigContext.Provider value={{prefix: 'avt'}}>
      <Child />
    </ConfigContext.Provider>
  );
}

const Child: React.FC = (props) => {
  const { prefix } = useContext<ConfigContextProps>(ConfigContext)
  return (
    <div>{prefix}</div>
  )
}

export default Demo;

useContext使用ConfigContext.Consumer或者定义Child.contextType的方式使用时方便,清晰容易理解。

const Child: React.FC = (props) => {
  const { prefix } = useContext<ConfigContextProps>(ConfigContext)
  return (
    <ConfigContext.Consumer>
      {
        ({ prefix }) => (
          <div>{prefix}</div>
        )
      }
    </ConfigContext.Consumer>
  )
}

总结

context在许多项目中应用都非常广泛,如redux中的状态共享就是使用context实现的。但是并不是所有的组件间传递状态都要使用context,因为它其实是违背的组件的概念,对组件有入侵性,可能导致组件无法复用。