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

如果在函数里定义了contextTypes作为一个属性,那么也可以在无状态的函数式组件里引用context。下面的代码显示了一个Button组件被写成一个无状态函数式组件。
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的更多相关文章

  1. React文档(十二)组合vs继承

    React拥有很强大的组合模型,我们建议使用组合来替代继承来重利用组件之间的代码. 在本章节中,我们将讨论一些开发者经常触及继承的问题,并且我们该如何使用组合来解决这些问题. 组合 一些组件事先不知道 ...

  2. React文档(十六)refs和DOM

    Refs 提供了一种方式,用于访问在 render 方法中创建的 DOM 节点或 React 元素. 在标准的React数据流中,props是使得父组件和子组件之间交互的唯一方式.你通过props重新 ...

  3. React文档(十九)不使用ES6

    通常你会将一个React组件定义成一个普通的js类: class Greeting extends React.Component { render() { return <h1>Hell ...

  4. React文档(十八)最佳性能

    在内部,React使用好几种聪明的技巧去最小化更新UI所需要的DOM操作.对于很多应用来说,使用React会使得构建用户界面非常之快而且不需要做太多专门的性能优化.虽然如此,还是有一些方法可以让你为R ...

  5. React文档(十五)使用propTypes进行类型检查

    注意: React.PropTypes 自 React v15.5 起已弃用.请使用 prop-types 库代替. 随着你的应用的开发,你会使用类型检查的方法来捕获很多bug.对于一些应用,你可以使 ...

  6. React文档(十四)深入JSX

    根本上,JSX只是为React.createElement(component, props, ...children)函数提供语法糖.JSX代码是这样的: <MyButton color=&q ...

  7. React文档(十)表单

    HTML表单元素和 React里的其他DOM元素有些不同,因为它们会保留一些内部的状态.举个例子,这个普通的表单接受唯一的name值: <form> <label> Name: ...

  8. Docker最全教程之使用Node.js搭建团队技术文档站(二十三)

    前言 各种编程语言均有其优势和生态,有兴趣的朋友完全可以涉猎多门语言.在平常的工作之中,也可以尝试选择相对适合的编程语言来完成相关的工作. 在团队技术文档站搭建这块,笔者尝试了许多框架,最终还是选择了 ...

  9. JAVA基础知识总结:一到二十二全部总结

    >一: 一.软件开发的常识 1.什么是软件? 一系列按照特定顺序组织起来的计算机数据或者指令 常见的软件: 系统软件:Windows\Mac OS \Linux 应用软件:QQ,一系列的播放器( ...

  10. Alink漫谈(二十二) :源码分析之聚类评估

    Alink漫谈(二十二) :源码分析之聚类评估 目录 Alink漫谈(二十二) :源码分析之聚类评估 0x00 摘要 0x01 背景概念 1.1 什么是聚类 1.2 聚类分析的方法 1.3 聚类评估 ...

随机推荐

  1. node多人聊天室搭建

    1.采用websocket: 为什么不用ajax的http:在用HTTP发送消息时,必须用一个新的TCP/IP连接.打开和关闭连接需要时间.此 外,因为每次请求都要发送HTTP头,所以传输的数据量也比 ...

  2. 简单尝试Spring Cloud Gateway

    简单尝试Spring Cloud Gateway 简介 Spring Cloud Gateway是一个API网关,它是用于代替Zuul而出现的.Spring Cloud Gateway构建于Sprin ...

  3. html5 css练习 定位布局

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  4. 无序数组求第k大/第k小的数

    根据http://www.cnblogs.com/zhjp11/archive/2010/02/26/1674227.html 博客中所总结的7种解法,我挑了其中的解法3和解法6进行了实现. 解法3: ...

  5. 第一个Python游戏窗口

    不废话,撸起袖子就是干. import pygame import sys pygame.init(); caption=pygame.display.set_caption("Python ...

  6. 升级python2.7, 实现python2.7与python3并存

    由于用到twilio模块, 所以需要升级一下python2, 但是又不想舍弃python2, 于是实现了简单的方法 python 先扔一块依赖 yum install zlib-devel bzip2 ...

  7. 算法(第四版)C# 习题题解——2.4

    写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 查找更方便的版本见:https ...

  8. Tomcat类加载

    一.为什么会有类加载 1.在类加载阶段,虚拟机需要完成以下3件事情 1)通过一个全限类定名来获取此类的二进制字节流 2) 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构 3)在内存中生成 ...

  9. opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

    本文部分内容转自 https://www.cnblogs.com/chaosimple/p/3182157.html 一.统计学概念 二.为什么需要协方差 三.协方差矩阵 注:上述协方差矩阵还需要除以 ...

  10. JAVA监听器Listener

    JAVA监听器Listener 一. 简介 监听器用于对web中内置对象的状态或者属性变化进行监听并做出相应响应的一种Servlet;在内置对象的生命周期中,产生.销毁等状态发生变化时,监听器就会进行 ...