本文的所涉及的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的情况下, 进行跨组件通信的方式.
如上图, 组件A需要传递信息给组件E, 需要通过props,先传递给组件B,然后把信息通过组件B传递给组件D,最后才传递给组件E. 这个过程中可能组件B和组件D不需要这些数据, 如果将来有组件插入到这个中间, 这个组件也需要传递props,就显得比较麻烦, 需要我们可以考虑使用Context来进行传递信息.
shouldComponentUpdate
返回false的影响, 使得组件的变化可控让我们看以下Demo:
// context.js
import React from 'react';
export const TodoListContext = React.createContext();
// 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>
);
}
}
// 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 的组成如下:
在16.8.6之后, React又提供了contextType Api用于支持Context, 它可以让我们通过this.context
的形式消费数据, 可以将上面的consumer.js文件修改如下:
// 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 删除。