useContext Hook 是如何工作的

想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!

所有这些新的React Hook之间都有一个宗旨:就是为了使函数组件像类组件一样强大。

useContext hook 与其它几个有点不一样,但它在特定场景下还是很有用的。

React 的 Context API 是一种在应用程序中深入传递数据的方法,而无需手动一个一个在多个父子孙之间传递 prop。当咱们需要的只是传递数据时,它可以作为像Redux这样的工具的一个很好的替代。

clipboard.png

使用 Context ,首先顶层先声明 Provier 组件,并声明 value 属性,接着在后代组件中声明 Consumer 组件,这个 Consumer 子组件,只能是唯一的一个函数,函数参数即是 Context 的负载。如果有多个 Context ,Provider 和 Consumer 任意的顺序嵌套即可。

此外我们还可以针对任意一个 Context 使用 contextType 来简化对这个 Context 负载的获取。但在一个组件中,即使消费多个 Context,contextType 也只能指向其中一个。

clipboard.png

在 Hooks 环境中,依旧可以使用 Consumer,但是 ContextType 作为类静态成员肯定是用不了。Hooks 提供了 useContext,不但解决了 Consumer 难用的问题同时也解决了 contextType 只能使用一个 context 的问题。

标准方式

使用 API的典型方法如下所示:

import React from "react";
import ReactDOM from "react-dom";

// 创建 Context
const NumberContext = React.createContext();
// 它返回一个具有两个值的对象
// { Provider, Consumer }

function App() {
  // 使用 Provider 为所有子孙代提供 value 值 
  return (
    <NumberContext.Provider value={42}>
      <div>
        <Display />
      </div>
    </NumberContext.Provider>
  );
}

function Display() {
  // 使用 Consumer 从上下文中获取 value
  return (
    <NumberContext.Consumer>
      {value => <div>The answer is {value}.</div>}
    </NumberContext.Consumer>
  );
}

ReactDOM.render(<App />, document.querySelector("#root"));

可以 CodeSandbox上看看运行效果。

使用 useContext 方式

使用 useContext hook 来重写上面的示例


import React, { useContext } from 'react';

// ...

function Display() {
  const value = useContext(NumberContext);
  return <div>The answer is {value}.</div>;
}

调用useContext,传入从React.createContext获取的上下文对象。

唯一需要注意的是你必须将整个上下文对象传递给useContext - 而不仅仅是Consumer, 当然如果忘记了,React会给出警告。

嵌套的 Consumers

你可能遇到这样的情况,咱们的组件需要从多个父上下文中接收数据,从而导致这样的代码

function HeaderBar() {
  return (
    <CurrentUser.Consumer>
      {user =>
        <Notifications.Consumer>
          {notifications =>
            <header>
              Welcome back, {user.name}!
              You have {notifications.length} notifications.
            </header>
          }
      }
    </CurrentUser.Consumer>
  );
}

这种大量嵌套只是为了接收两个值。下面是使用useContext时的效果:

function HeaderBar() {
  const user = useContext(CurrentUser);
  const notifications = useContext(Notifications);

  return (
    <header>
      Welcome back, {user.name}!
      You have {notifications.length} notifications.
    </header>
  );
}

总结

useContext 接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <CountContext.Provider> 的 value prop 决定。

当组件上层最近的 <CountContext.Provider> 更新时,该 Hook 会触发重渲染,并使用最新传递给 CountContext provider 的 context value 值。

别忘记 useContext 的参数必须是 context 对象本身:

  • 正确: useContext(MyContext)
  • 错误: useContext(MyContext.Consumer)
  • 错误: useContext(MyContext.Provider)

调用了 useContext 的组件总会在 context 值变化时重新渲染。如果重渲染组件的开销较大,你可以 通过使用 memoization 来优化。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

参考:

https://daveceddia.com/usecon...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值