React文档(二十二)context
React中,通过React组件可以很容易地追踪数据流。当你关注一个组件,你可以发现哪一个props被传递了,这样使得你的应用很容被推断。
在一些情况下,你想要传递数据通过组件树而不需要去手动在每一层传递。你可以直接使用强大的context API。
为什么不使用context
大量的应用不需要使用context。
如果你希望你的应用稳定,不要使用context。这是一个实验性的API在未来的版本中有可能会崩溃。
如果你不熟悉state管理库就类似于Redux或者Mobx,不要使用context。对于很多实际的应用,这些库和它们的React绑定实现是很好的选择来管理state,这对于很多组件都有重大意义。解决问题最好的方案更像是Redux而不是context。
如果你不是一个有经验的React开发者,不要使用context。有更好的方式去实现功能通过使用props和state。
如果你坚持使用context而不管这些警告,那么就请试图隔离你使用context在一个较小的范围并且避免直接使用context API为了当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组件(context提供者)添加childContextTypes属性和getChildContext方法,React会自动传递信息并且任何子树里的组件(在这个例子,Button组件)都可以获取到这个信息通过定义contextTypes。
如果contextTypes没有定义,那么context会是一个空对象。
父子联合
context也可以让你建造一套可以让父组件和子组件通信的API。举个例子,一个这样运作的库叫做React Router v4:
import { 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组件传递一些信息,每一个Link和Route都可以和包含的Router通信。
在你使用类似的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
const Button = ({children}, context) =>
<button style={{background: context.color}}>
{children}
</button>; Button.contextTypes = {color: React.PropTypes.string};
更新context
不要这样做。
React有一个更新context的API,但是它实质上已经损坏你不应该使用它。
getChildContext函数当props或者state改变的时候会被调用。为了在context中更新数据,使用this.setState来触发本地的state更新。这样将会触发一个新的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。这个博客有一个很好地解释关于为什么这是一个问题以及你怎样避开它。
React文档(二十二)context的更多相关文章
- React文档(十二)组合vs继承
React拥有很强大的组合模型,我们建议使用组合来替代继承来重利用组件之间的代码. 在本章节中,我们将讨论一些开发者经常触及继承的问题,并且我们该如何使用组合来解决这些问题. 组合 一些组件事先不知道 ...
- React文档(十六)refs和DOM
Refs 提供了一种方式,用于访问在 render 方法中创建的 DOM 节点或 React 元素. 在标准的React数据流中,props是使得父组件和子组件之间交互的唯一方式.你通过props重新 ...
- React文档(十九)不使用ES6
通常你会将一个React组件定义成一个普通的js类: class Greeting extends React.Component { render() { return <h1>Hell ...
- React文档(十八)最佳性能
在内部,React使用好几种聪明的技巧去最小化更新UI所需要的DOM操作.对于很多应用来说,使用React会使得构建用户界面非常之快而且不需要做太多专门的性能优化.虽然如此,还是有一些方法可以让你为R ...
- React文档(十五)使用propTypes进行类型检查
注意: React.PropTypes 自 React v15.5 起已弃用.请使用 prop-types 库代替. 随着你的应用的开发,你会使用类型检查的方法来捕获很多bug.对于一些应用,你可以使 ...
- React文档(十四)深入JSX
根本上,JSX只是为React.createElement(component, props, ...children)函数提供语法糖.JSX代码是这样的: <MyButton color=&q ...
- React文档(十)表单
HTML表单元素和 React里的其他DOM元素有些不同,因为它们会保留一些内部的状态.举个例子,这个普通的表单接受唯一的name值: <form> <label> Name: ...
- Docker最全教程之使用Node.js搭建团队技术文档站(二十三)
前言 各种编程语言均有其优势和生态,有兴趣的朋友完全可以涉猎多门语言.在平常的工作之中,也可以尝试选择相对适合的编程语言来完成相关的工作. 在团队技术文档站搭建这块,笔者尝试了许多框架,最终还是选择了 ...
- JAVA基础知识总结:一到二十二全部总结
>一: 一.软件开发的常识 1.什么是软件? 一系列按照特定顺序组织起来的计算机数据或者指令 常见的软件: 系统软件:Windows\Mac OS \Linux 应用软件:QQ,一系列的播放器( ...
- Alink漫谈(二十二) :源码分析之聚类评估
Alink漫谈(二十二) :源码分析之聚类评估 目录 Alink漫谈(二十二) :源码分析之聚类评估 0x00 摘要 0x01 背景概念 1.1 什么是聚类 1.2 聚类分析的方法 1.3 聚类评估 ...
随机推荐
- datetimepicker 使用
首先引入 <%--日历样式--%> <link rel="stylesheet" type="text/css" href="< ...
- [CentOS] rsync同步目录进行备份文件
操作不难,网上一堆.这里列几个 CentOS7 参考地址: https://www.server-world.info/en/note?os=CentOS_7&p=rsync Copy fil ...
- 论文阅读(XiangBai——【CVPR2017】Detecting Oriented Text in Natural Images by Linking Segments)
XiangBai——[CVPR2017]Detecting Oriented Text in Natural Images by link Segments 目录 作者和相关链接 方法概括 方法细节 ...
- 2018软件工程W班第一次助教小结
我是数计学院实验教学中心的一名老师,机缘巧合之下,这个学期跟着汪老师上<软件工程实践>这门课.之前有陆续听说过<构建之法>这本书,记得好像学院还有主办过研讨会.对于这门实践课, ...
- django2.2/mysql ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3
报错环境 python=3.6.5,django=2.2,PyMySQL=0.9.3 …… django.core.exceptions.ImproperlyConfigured: mysqlcl ...
- Mac 下 实现终端跳转 服务器 不用输入密码
首先需要安装 expect 安装 expect 需要 tcl 依赖 第一步 下载tcl http://www.tcl.tk/software/tcltk/downloadnow84.tml 将下载好 ...
- 数据库session立即生效(64---8192) SCOPE参数
SCOPE=MEMORY|SPFILE|BOTH 指示了修改参数时的“作用域”: SCOPE=MEMORY :只在实例中修改,重启数据库后此次修改失效. SCOPE=SPFILE :只修改SPFILE ...
- asp.net处理机制管道事件
自定义的托管模块HTTP模块可以向System.Web.HttpApplication对象注册下面一系列事件: AcquireRequestState 当ASP.NET运行时准备好接收当前HTTP请求 ...
- winform Combobox出现System.Data.DataRowView的解决的方法
个人总结: 1.触发了SelectedIndexChanged事件时:comboBox1.DataSource = dt;要放在comboBox1.SelectedIndex = 0;的上面 comb ...
- for 循环,如果判断那里用到了一个函数,每次循环一次都会调用一次函数,如图
但用高级for,可以不用每次都调用方法