• Context
    • 从树里自动传递info
    • 父子耦合
    • 在生命周期方法里引用 context
    • 在无状态函数组件里引用 context
    • 什么时候不用 context
    • 已知的限制

    Context

    React最大的优势之一是他很容易从你的React组件里跟踪数据流动。当你看着一个组件,你可以很容易准确看出哪个props被传入,这让你的APP很容易推断。

    偶尔,你想通过组件树传递数据,而不在每一级上手工下传prop,React的 “context” 让你做到这点。

    > 注意:
    > 
    > Context是一个先进的实验性特性.这个 API 很可能在未来版本变化.
    >

    大多数应用将不会需要用到 context. 尤其是如果你刚开始用React,你很可能不会想用 context.使用 context 将会使你的代码很难理解因为它让数据流不清晰.它类似于在你的应用里使用全局变量传递state.

    如果你必须使用 context ,保守的使用它

    不论你正在创建一个应用或者是库,试着分离你对 context 的使用到一个小区域,并尽可能避免直接使用 context API,以便在API变动时容易升级.

    从树里自动传递info

    假设你有一个这样的结构:

    1. var Button = React.createClass({
    2. render: function() {
    3. return (
    4. <button style={{'{{'}}background: this.props.color}}>
    5. {this.props.children}
    6. </button>
    7. );
    8. }
    9. });
    10. var Message = React.createClass({
    11. render: function() {
    12. return (
    13. <div>
    14. {this.props.text} <Button color={this.props.color}>Delete</Button>
    15. </div>
    16. );
    17. }
    18. });
    19. var MessageList = React.createClass({
    20. render: function() {
    21. var color = "purple";
    22. var children = this.props.messages.map(function(message) {
    23. return <Message text={message.text} color={color} />;
    24. });
    25. return <div>{children}</div>;
    26. }
    27. });

    在这里例子里,我们手工穿透一个 color prop 以便于恰当格式化 ButtonMessage 组件.主题是一个很好的例子,当你可能想整个子树都可以访问一部分信息时(比如color). 使用 context 我们可以自动传过这个树:

    1. var Button = React.createClass({
    2. contextTypes: {
    3. color: React.PropTypes.string
    4. },
    5. render: function() {
    6. return (
    7. <button style={{'{{'}}background: this.context.color}}>
    8. {this.props.children}
    9. </button>
    10. );
    11. }
    12. });
    13. var Message = React.createClass({
    14. render: function() {
    15. return (
    16. <div>
    17. {this.props.text} <Button>Delete</Button>
    18. </div>
    19. );
    20. }
    21. });
    22. var MessageList = React.createClass({
    23. childContextTypes: {
    24. color: React.PropTypes.string
    25. },
    26. getChildContext: function() {
    27. return {color: "purple"};
    28. },
    29. render: function() {
    30. var children = this.props.messages.map(function(message) {
    31. return <Message text={message.text} />;
    32. });
    33. return <div>{children}</div>;
    34. }
    35. });

    通过添加 childContextTypesgetChildContextMessageList ( context 提供),React下传信息到子树中的任何组件(在这个例子中, Button可以由定义 contextTypes来访问它).

    如果 contextTypes 没有定义,那么 this.context 将是一个空对象.

    父子耦合

    Context 同样可以使你构建这样的 APT:

    1. <Menu>
    2. <MenuItem>aubergine</MenuItem>
    3. <MenuItem>butternut squash</MenuItem>
    4. <MenuItem>clementine</MenuItem>
    5. </Menu>

    通过在 Menu 组件下传相关的信息,每个 MenuItem 可以与包含他们的 Menu 组件沟通.

    在你用这个API构建组件以前,考虑一下是否有清晰的替代方案 我们 喜欢像这样简单的用数组传递items:

    1. <Menu items={['aubergine', 'butternut squash', 'clementine']} />

    记住你同样可以在props里传递整个React组件,如果你想.

    在生命周期方法里引用 context

    如果 contextTypes 在一个组件中定义,接下来的生命周期方法会收到一个额外的参数, context 对象:

    1. void componentWillReceiveProps(
    2. object nextProps, object nextContext
    3. )
    4. boolean shouldComponentUpdate(
    5. object nextProps, object nextState, object nextContext
    6. )
    7. void componentWillUpdate(
    8. object nextProps, object nextState, object nextContext
    9. )
    10. void componentDidUpdate(
    11. object prevProps, object prevState, object prevContext
    12. )

    在无状态函数组件里引用 context

    无状态函数同样能够引用 context 如果 contextTypes 被定义为函数的属性.下面的代码展示了被写为无状态函数组件的 Button 组件.

    1. function Button(props, context) {
    2. return (
    3. <button style={{'{{'}}background: context.color}}>
    4. {props.children}
    5. </button>
    6. );
    7. }
    8. Button.contextTypes = {color: React.PropTypes.string};

    什么时候不用 context

    正像全局变量是在写清晰代码时最好要避免的,你应该在大多数情况下避免使用context. 特别是,在用它来”节省输入”和代替显示传入props时要三思.

    context最好的使用场景是隐式的传入登录的用户,当前的语言,或者主题信息.要不然所有这些可能就是全局变量,但是context让你限定他们到一个单独的React树里.

    不要用context在组件里传递你的模型数据.通过树显示的传递你的数据更容易理解.使用context使你的组件更耦合和不可复用,因为 依赖于他们在哪里渲染,他们会表现不同的行为.

    已知的限制

    如果一个由组件提供的context值变动,使用那个值的子级不会更新,如果一个直接的父级从 shouldComponentUpdate 返回 false .详见 issue #2517 .