14. react - context

1. react 中的 context 使用了生产者消费者模式 【Provider和Customer模式】。

2. 可以在顶层的Provider中传入value,在子孙级的Consumer中获取该值,并且能够传递函数,用来修改context

// 1. context.js 中
import React from 'react'

const ThemeContext = React.createContext({
    theme: 'dark',
    toggle: () => {}, //向上下文设定一个回调方法
});
// const ThemeContext = React.createContext('light');

export default ThemeContext

// 2. index.js 中
import ThemeContext from './context'
import Content from './Toolbar'

const themes = {
  dark: 'dark',
  light: 'light'
}
// //运行APP
class App extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = () => { //设定toggle方法,会作为context参数传递
      this.setState(state => ({
        theme:
          state.theme === themes.dark
            ? themes.light
            : themes.dark,
      }));
    };

    this.state = {
      theme: themes.light,
      toggle: this.toggle,
    };
  }

  render() {
    //state包含了toggle方法
    return (
      <ThemeContext.Provider value={this.state}>
        <Content />
      </ThemeContext.Provider>
    );
  }
}
ReactDOM.render(
  <App />,
  document.getElementById('root')
)

// 3. 中间组件 Toolbar.js
import React from 'react'
import Button from './ThemeButton'

export default class Toolbar extends React.Component{
    constructor (props) {
        super(props)
    }

    render () {
        return (
            <div>
                <Button />
            </div>
        )
    }
    
}

// 4. 子组件 Button.js
import React from 'react'
import ThemeContext from './context'

class Button extends React.Component {
    constructor (props) {
        super(props)
    }

    render () {
      // context.Consumer 中必须是一个函数式组件。这个函数接收当前的 context 值,返回一个 React 节点。
return ( <ThemeContext.Consumer> {({theme, toggle}) => ( <button onClick={toggle} style={{backgroundColor: theme}}> {theme} </button> )} </ThemeContext.Consumer> ) } }

3. 如何使用 this.context: 挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你能在任何生命周期中使用 this.context

import React from 'react'
import ThemeContext from './utils'

class Button extends React.Component {
    constructor (props) {
        super(props)
    }

    render () {
        console.log(this.context, "BBBBBBBBBBBB")
        return (
            <ThemeContext.Consumer>
                {({theme, toggle}) => (
                <button
                    onClick={toggle}
                    style={{backgroundColor: theme}}>
                    {theme}
                </button>
                )}
            </ThemeContext.Consumer>
        )
    }
}

Button.contextType = ThemeContext  //调用后可以在 Button 的组件的类中使用this.context

export default Button

4. 那些生命周期中可以使用 this.context

constructor(props, context)
componentWillReceiveProps(nextProps, nextContext)
shouldComponentUpdate(nextProps, nextState, nextContext)
componentWillUpdate(nextProps, nextState, nextContext)
componentDidUpdate(prevProps, prevState, prevContext)

import React from 'react'
import ThemeContext from './utils'

class Button extends React.Component {
    constructor (props, context) {
        super(props, context)
        console.log(context)
    }

    componentWillReceiveProps(nextProps, nextContext) {
        console.log(nextContext, "componentWillReceiveProps  context")
    }

    shouldComponentUpdate(nextProps, nextState, nextContext) {
        console.log(nextContext, "shouldComponentUpdate  context")
    }


    componentWillUpdate(nextProps, nextState, nextContext) {
        console.log(nextContext, "componentWillUpdate  context")
    }


    componentDidUpdate(prevProps, prevState, prevContext) {
        console.log(prevContext, "componentDidUpdate  context")
    }

    render () {
        console.log(this.context, "BBBBBBBBBBBB")
        return (
            <ThemeContext.Consumer>
                {({theme, toggle}) => (
                <button
                    onClick={toggle}
                    style={{backgroundColor: theme}}>
                    {theme}
                </button>
                )}
            </ThemeContext.Consumer>
        )
    }
}

Button.contextType = ThemeContext

export default Button

 

5. React context的局限性

1. 在组件树中,如果中间某一个组件 ShouldComponentUpdate returning false 了,会阻碍 context 的正常传值,导致子组件无法获取更新。
2. 组件本身 extends React.PureComponent 也会阻碍 context 的更新。

 

posted @ 2020-06-11 16:34  monkey-K  阅读(150)  评论(0编辑  收藏  举报