2022年前端React的100道面试题的第14题:Context的使用

379 阅读3分钟

问题

React17 关于 Context 的使用正确的是?

选项

A. 它提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。

B. 通过新旧值检测来确定变化,使用了与 immutable.is 相同的算法。

C. 渲染一个订阅了 Context 对象的组件,则此组件会从组件树上层中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。

D. 只有当组件所处的树中没有匹配到 Provider 时,以及 Provider 的 value 为 undefined 时,消费组件的 defaultValue 的才会生效。

答案

A、C

纠错

B. 通过新旧值检测来确定变化,使用了与 Object.is 相同的浅比较算法。(而 immutable.is 是深比较算法方式)

D. 将 undefined 传递给 Provider 的 value 时,消费组件的 defaultValue 不会生效。只有当组件所处的树中没有匹配到 Provider 时,其 defaultValue 参数才会生效。

讲解

Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。

个人认为官方文档写得非常详细,关于如何使用以及注意事项,网上很多文档基本都是照搬的,所以我就不做重复行为了,下面也是把官方文档中几个容易造成问题的点提炼出来聊聊吧。

Provider 的 value 值

因为 context 是根据 “数据的引用标识” 来决定何时进行渲染,就是拿 value 属性值进行浅比较,如果此值是一个字面量对象,那么 Provider 所在的组件重新渲染时,会生成一个新的 value,从而导致所有的 consumers 组件都被触发更新。

例如下面的代码:

class App extends React.Component {
  render() {
    return (
      <MyContext.Provider value={{something: 'something'}}>
        <Toolbar />
      </MyContext.Provider>
    );
  }
}

因此建议以对象的方式存储 value 值:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: {something: 'something'},
    };
  }
​
  render() {
    return (
      <MyContext.Provider value={this.state.value}>
        <Toolbar />
      </MyContext.Provider>
    );
  }
}

官方称之为 “动态 Context” 的实践方式。

获取context的方式

目前版本支持获取 context 数据的方式有以下几种:

  • 在类组件中通过 Class.contextType = MyContext; 的方式绑定单个 context,然后用 this.context 来使用数据。
  • 基于 public class fields 语法static contextType = MyContext; 方式同上方式。
  • 在函数组件中通过 const value = useContext(MyContext); 的方式获取单个 context。
  • Context.Consumer 和函数值的方式获取单个 context。
  • 以上都是单 context 的方式,如果组件依赖多个,还可以在父级中获取需要的 context,然后通过 props 的方式传入。

如果多个组件都依赖一批 context 数据的话,应该是在设计 context 时,就要考虑清楚对应的职责,进行数据整合。

默认值

只要没有提供 Context.Provider 就会使用 React.createContext() 方法传入的数据作为默认值,且默认值的类型是不限制的,可以是任意基础类型数值。

因此最简单使用 context 方式:

const HiContext = React.createContext('hello');
​
class App extends React.Component {
  render() {
    <HiContext.Consumer>
      {(text) => (<h1>{text}</h1>)}
    </HiContext.Consumer>
  }
}

需要注意 React 16 版本之后不再推荐使用 getChildContext() 方法,给组件设置默认值。

资料

zh-hans.reactjs.org/docs/legacy…

developer.mozilla.org/en-US/docs/…

来源

搜索《考试竞技》微信小程序