React高级指南(九)【Context】
来源:互联网 发布:muji懒人沙发 知乎 编辑:程序博客网 时间:2024/06/05 14:08
在React中,在React组件中很容易追踪数据流。当你观察组件时,你可以找出哪些属性(props)被传递,这使得你的应用非常容易理解。
在某些场景下,你想在整个组件树中传递数据,但却不想手动地在每一层传递属性。你可以直接在React中使用强大的context
API解决上述问题。
为什么不要使用Context
绝大多数的应用程序不需要使用context
。
如果你希望使用应用程序更加稳定就不要使用context。这只是一个实验性的API并且可能在未来的React版本中移除。
如果你不熟悉React或者Mobx这类state管理库,就不要使用context
。对于许多应用程序,上述库和state
绑定是管理state
不错的选择。Redux
相比context
是更好的解决方法。
如果你不是一个有经验的React开发者,就不要使用context
。更好的方式是使用props
和state
。
如果你不顾这些警告仍然坚持使用context
,尝试着将context
的使用隔离在一个将小的范围内,并且在可能的情况下直接使用context
,以便在API改变的时候进行升级。
如何使用Context
假定有下面的结构:
class Button extends React.Component { render() { return ( <button style={{'{{'}}background: this.props.color}}> {this.props.children} </button> ); }}class Message extends React.Component { render() { return ( <div> {this.props.text} <Button color={this.props.color}>Delete</Button> </div> ); }}class MessageList extends React.Component { render() { const color = "purple"; const children = this.props.messages.map((message) => <Message text={message.text} color={color} /> ); return <div>{children}</div>; }}
在这个例子中,我们手动地传递color
属性使得Button
和Message
设置正确的样式。使用context
,我们可以自动在组件树中传递属性。
class Button extends React.Component { render() { return ( <button style={{'{{'}}background: this.context.color}}> {this.props.children} </button> ); }}Button.contextTypes = { color: React.PropTypes.string};class Message extends React.Component { render() { return ( <div> {this.props.text} <Button>Delete</Button> </div> ); }}class MessageList extends React.Component { getChildContext() { return {color: "purple"}; } render() { const children = this.props.messages.map((message) => <Message text={message.text} /> ); return <div>{children}</div>; }}MessageList.childContextTypes = { color: React.PropTypes.string};
通过给MessageList
添加childContextTypes
和childContextTypes
(context
提供者),React自动地向下传递信息,任何子树(例如:Button
)可以通过定义contextTypes
访问到属性。
如果没有定义contextTypes
,context
将是一个空的object。
父子耦合
Context可以构建API使得父组价和子组件进行相互通信。例如:React Router V4工作机制如下:
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';const BasicExample = () => ( <Router> <div> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/about">About</Link></li> <li><Link to="/topics">Topics</Link></li> </ul> <hr /> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> <Route path="/topics" component={Topics} /> </div> </Router>);
通过从Router
中传递相关信息,Router
中的每一个Link
和Route
都可以与之通信。
在你构建包含类似于上述的API的组件之前,考虑是否有其他的更清晰的选择。例如,你可以传递整个React组件作为props传递。
在生命周期函数中使用Context
如果contextTypes
在组件中定义,下列的生命周期函数将接受一个额外的参数:context
对象
constructor(props, context)
componentWillReceiveProps(nextProps, nextContext)
shouldComponentUpdate(nextProps, nextState, nextContext)
componentWillUpdate(nextProps, nextState, nextContext)
componentDidUpdate(prevProps, prevState, prevContext)
在无状态的函数式组件中使用Context
如果contextType
被定义为函数的属性,无状态函数式组件也能够引用context
。下面的代码演示了一个Button
状态的函数式组件。
const Button = ({children}, context) => <button style={{'{{'}}background: context.color}}> {children} </button>;Button.contextTypes = {color: React.PropTypes.string};
更新Context
别这么做!
React有一个API更新context,但是它打破了基本流程,不应该使用。
getChildContext
函数将会在每次state
或者props
改变时调用。为了更新context
中的数据,使用this.setState
触发本地状态的更新。这将触发一个的context
并且数据的改变可以被子元素收到。
class MediaQuery extends React.Component { constructor(props) { super(props); this.state = {type:'desktop'}; } getChildContext() { return {type: this.state.type}; } componentDidMount() { const checkMediaQuery = () => { const type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile'; if (type !== this.state.type) { this.setState({type}); } }; window.addEventListener('resize', checkMediaQuery); checkMediaQuery(); } render() { return this.props.children; }}MediaQuery.childContextTypes = { type: React.PropTypes.string};
问题在于,组件提供的context
值改变,后代元素如果shouldComponentUpdate
返回false
那么context
的将不会更新。这使得使用context
的组件完全失控,所以基本上没有办法可靠的更新context
。这篇blog很好的解释了为什么这是一个问题并如果绕过它。
- React高级指南(九)【Context】
- React高级指南(八)【Reconciliation】
- React高级指南(六)【React Without ES6】
- React高级指南(七)【React Without JSX】
- React-navigation导航系统(3)-高级指南
- React高级指南(一)【JSX In Depth】
- React高级指南(二)【Typechecking With PropTypes】
- React高级指南(四)【Uncontrolled Components】
- React高级指南(五)【Optimizing Performance】
- React高级指南(十)【Web Components】
- React高级指南(十一)【Higher Order Components】
- React高级教程(es6)——(3)React中的Context
- React高级指南(三)【Refs and the DOM】
- React高级指南(十二)【Integrating with Other Libraries】
- react中context学习
- React context/contextTypes
- React总结12:context
- react 上下文(Context)
- C malloc
- UE4之去掉屏幕提示
- 学生的等级
- Error reading from file descriptor 13: Input/output error
- Mathematica7.0中文免费版下载
- React高级指南(九)【Context】
- html拾遗第2天,页面上进行权限控制
- 【微积分】复习
- java-11.11作业
- Atlas – MySQL 切片器 介绍
- 谷歌地图将推就餐等候显示功能 错峰用餐更省时
- 谈一谈安装mysql给我带来的中文乱码问题
- cocos2dx 常见的22种特效 3D特效
- Java并发编程札记-(一)基础-03线程的生命周期