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的最佳应用情景应该是像用户登录、应用语言或者是应用主题的这一类情景,这些都是真实的全局变量。