前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >解读React的新Context API

解读React的新Context API

原创
作者头像
JianLiang
修改2019-05-07 10:21:12
1.5K0
修改2019-05-07 10:21:12
举报
文章被收录于专栏:进击的全栈

什么是Context Api

本文的所涉及的React版本为16.8.6; Context provides a way to pass data through the component tree without having to pass props down manually at every level. Context Api是React提供的能够在全局之间共享数据的一个Api, 原有的React进行数据的通信的方式是通过props进行数据传递, 而Context提供了一个在不需要props的情况下, 进行跨组件通信的方式.

1557155591949.png
1557155591949.png

如上图, 组件A需要传递信息给组件E, 需要通过props,先传递给组件B,然后把信息通过组件B传递给组件D,最后才传递给组件E. 这个过程中可能组件B和组件D不需要这些数据, 如果将来有组件插入到这个中间, 这个组件也需要传递props,就显得比较麻烦, 需要我们可以考虑使用Context来进行传递信息.

新Context API的特点

  1. 采用声明式的写法
  2. 可以跨组件进行通信, 顶层组件提供数据, 目标组件订阅数据
  3. 不受中间组件的shouldComponentUpdate返回false的影响, 使得组件的变化可控

让我们看以下Demo:

代码语言:txt
复制
// context.js
import React from 'react';

export const TodoListContext = React.createContext();
代码语言:txt
复制
// provide.js
import React from 'react';
import { TodoListContext } from './context';

const { Provider } = TodoListContext;
export default class TodoListPorvider extends React.Component {
  state = {
    inputValue: '111',
    list: [],
  }
  handleChange = (e) => {
    this.setState({
      inputValue: e.target.value
    });
  }
  handleClick = () => {
    const newList = [...this.state.list];
    newList.push(this.state.inputValue);
    this.setState({
      inputValue: '',
      list: newList,
    });
  }
  handleDelete = (index) => {
    const newList = [...this.state.list];
    newList.splice(index, 1);
    this.setState({
      list: newList
    });
  }
  render() {
    return (
      <div style={{ padding: 20, backgroundColor: '#fff' }}>
        <Provider value={{
           state: this.state,
           handleChange: this.handleChange,
           handleClick: this.handleClick,
           handleDelete: this.handleDelete,
        }}>
          {this.props.children}
        </Provider>
      </div>
    );
  }
}
代码语言:txt
复制
// consumer.js
import React from 'react';
import { TodoListContext } from './context';
import TodoListProvide from './provide';

const { Consumer } = TodoListContext;
console.log(TodoListContext);
const Search = props => {
  return (
    <div>
      <input value={props.inputValue} onChange={props.handleChange} style={{ marginRight: 10 }}/>
      <button onClick={props.handleClick}>添加</button>
    </div>
  )
}

const TodoList = props => {
  return (
    <div>
        {
          props.list.map((item, index) => {
            return <li onClick={() => props.handleDelete(index)} key={index}>{item}</li>
          })
        }
      </div>
  );
}

export default class TodolistCousumer extends React.Component {
  render() {
    return (
      <TodoListProvide>
        <Consumer>
          {
            context => (
              <div>
                <Search inputValue={context.state.inputValue} handleChange={context.handleChange} handleClick={context.handleClick} />
                <TodoList list={context.state.list} handleDelete={context.handleDelete} />
              </div>
            )
          }
        </Consumer>
      </TodoListProvide>
    )
  }
}

新的Context Api 的组成如下:

  • React.createContext 初始化一个Context
  • Provider 作为顶层组件用于提供数据(可以是字符串,数字, 甚至是函数), 数据会存放在一个名为value的属性中
  • Consumer 作为消费组件用于订阅数据, 它可以出现在组件树的任意位置(需要被包裹着Provider之中)

在16.8.6之后, React又提供了contextType Api用于支持Context, 它可以让我们通过this.context的形式消费数据, 可以将上面的consumer.js文件修改如下:

代码语言:txt
复制
// consumer.js
import React from 'react';
import { TodoListContext } from './context';
import TodoListProvide from './provide';

const { Consumer } = TodoListContext;
console.log(TodoListContext);
const Search = props => {
  return (
    <div>
      <input value={props.inputValue} onChange={props.handleChange} style={{ marginRight: 10 }}/>
      <button onClick={props.handleClick}>添加</button>
    </div>
  )
}

const TodoList = props => {
  return (
    <div>
        {
          props.list.map((item, index) => {
            return <li onClick={() => props.handleDelete(index)} key={index}>{item}</li>
          })
        }
      </div>
  );
}

export default class TodolistCousumer extends React.Component {
  render() {
    return (
      <TodoListProvide>
        <div>
            <Search inputValue={this.context.state.inputValue} handleChange={this.context.handleChange} handleClick={this.context.handleClick} />
            <TodoList list={this.context.state.list} handleDelete={this.context.handleDelete} />
        </div>
      </TodoListProvide>
    )
  }
}
TodolistCousumer.contextType = TodoListContext

通过contextType, 可以在组件的任意位置进行调用(包括生命周期函数内)

总结

Context Api 是提供了一个'上下文'对象(TodoListContext), 通过这个对象我们可以在目标组件(TodoListPorvider)中订阅数据, 每当数据的变动时, 对应的消费组件(TodolistCousumer) 都能够接受到数据从而发生改变, 而消费组件可以出现在组件树的任意位置, 不受到中间组件的影响, 为我们的跨组件通信提供的便利的手段.

参考链接

新Contex Api: https://reactjs.org/docs/context.html#when-to-use-context

旧Context Api: https://5a1dbcf14c4b93299e65b9a9--reactjs.netlify.com/docs/context.html

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是Context Api
  • 新Context API的特点
  • 总结
  • 参考链接
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档