React-React-Context

15次阅读

共计 1995 个字符,预计需要花费 5 分钟才能阅读完成。

props
当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)转换为单个对象传递给组件,这个对象被称之为“props”。

function Welcome(props) {return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

React 调用 Welcome 组件,并将 {name: ‘Sara’} 作为 props 传入。
注意:组件无论是使用函数声明还是通过 class 声明,都决不能修改自身的 props。

context
在一个典型的 React 应用中,数据是通过 props 属性自上而下(由父及子)进行传递的。但是如果有些属性是应用程序中许多组件都需要的,此时我们希望可以共享这些值,于是 Context 就出现了。
Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。
Context 就像我们在应用中使用全局变量一样。我们应当谨慎使用 Context。

var Button = React.createClass({
  contextTypes: {color: React.PropTypes.string},
  render: function() {
    return (<button style={{background: this.context.color}}>
        {this.props.children}
      </button>
    );
  }
});

var Message = React.createClass({render: function() {
    return (
      <div>
        {this.props.text} <Button>Delete</Button>
      </div>
    );
  }
});

var MessageList = React.createClass({
  childContextTypes: {color: React.PropTypes.string},
  getChildContext: function() {return {color: "purple"};
  },
  render: function() {
    return (
    <div>
        <Message text='警告'/>
    </div>
    );
  }
});

在这个例子中,我们想在 MessageList 组件中,传递 color 值到子组件 Message 的子组件 Button 中(即越级传值),需要以下步骤。

首先,我们需要在 MessageList 组件中定义 childContextTypes 和 getChildContext。
其次,我们需要在 Button 组件中定义 contextTypes。
这样我们就可以在 Button 组件中使用这些值了。

备注:React 能够自动地把信息 (数据) 向所有设置了 contextTypes 的子树进行传递。如果 contextTypes 在子组件中还没有定义,那 this.context 将会是一个空对象。

那我们应该怎么更新组件的 Context 呢?
答案是,把 Context 和组件的 State 关联起来,当组件的 state 或者 props 改变的时候,getChildContext 函数会自动调用,更新 Context 并把这个新的 Context 和其他改变一起传输到子树。

var MediaQuery = React.createClass({getInitialState: function(){return {type:'desktop'};
  },
  childContextTypes: {type: React.PropTypes.string},
  getChildContext: function() {return {type: this.state.type};
  },
  componentDidMount: function(){var checkMediaQuery = function(){var type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';
      if (type !== this.state.type){this.setState({type:type}); 
      }
    };

    window.addEventListener('resize', checkMediaQuery);
    checkMediaQuery();},
  render: function(){return this.props.children;}
});

其实在大多数情况下,为了代码的清晰可观,我们都应该尽可能避免使用 Context(就像全局变量一样)。Context 的最佳应用情景应该是像用户登录、应用语言或者是应用主题的这一类情景,这些都是真实的全局变量。

正文完
 0