Context:
Context 提供了一种在组件之间共享值的方式,而不必显式地通过组件树的逐层传递 props。如果获取值和使用值的层级相隔很远,或者需要使用这个值的组件很多很分散,则可以使用Context来共享数据,避免使用大量重复的props来传递值。如果只是一个组件需要使用这个值,可以在产生这个值的位置生成这个组件,然后用props层层传递到组件实际展示的位置。
React.createContext:
创建一个Context对象,当React渲染一个订阅了这个context对象的组件,这个组件会从组件树中离自身最近的那个匹配的Provider中读取到当前的context值。
1 | const MyContext = React.createContext(defaultValue) |
只有当组件所处的树中没有匹配到Provider时,其defaultValue参数才会生效,这有助于在不使用Provider包装组件的情况下对组件进行测试。注意:将undefined传递给Provider的value时,defaultValue不会生效。
Context.Provider:
每个Context对象都会返回一个Provider React组件,它允许消费组件订阅context的变化
1 | <MyContext.Provider value={"某个值"}> |
Provider接收一个value属性传递给消费组件,一个Provider可以和多个消费组件有对应关系,多个Provider也可以嵌套使用,里层的会覆盖外层的数据。
当Provider的value值发生变化时,它内部的所有消费组件都会重新渲染。
Class.ContextType:
挂载在class上的contextType属性会被重赋值为一个由React.createContext创建的Context对象,这使你使用this.context来消费最近Context上的那个值,你可以在任何生命周期中访问到它,包括render函数。
Context的更新不受父组件和自身shouldComponentUpdate的影响,经过的生命周期是render -> componentDidUpdate
1 | class MyClass extends React.Component { |
Context.Consumer:
如果需要使用多个Context上的值,只有一个ContextType是不够的,使用Context.Consumer支持获取多个Context上的值,如下图所示:
1 | import React from 'react' |
1 | import React from 'react' |
1 | import React,{Component} from 'react' |
然后在ThemeButton组件中使用两个Context的提供的值:
1 | import React,{Component} from 'react' |
contextType与Consumer的比较:contextType在一个组件中只能指向一个Context,然后可以通过this.context在组件的任意位置使用对应Provider提供的值。缺点就是只能使用一个Context。Consumer可以使用多个,获取不同类型Provider的值。但是由于使用了标签的语法,只能在render和相关的范围内使用。组件中应尽可能使用Consumer来获取Context上的值,把contextType的位置留出来,避免后续必须用到contextType的时候没有contextType可以用了。