?
This document uses PHP Chinese website manual Release
注意:
React.PropTypes
自從React v15.5以來,它已經(jīng)進(jìn)入了一個(gè)不同的包。請(qǐng)使用該prop-types
庫,而不是定義contextTypes
。我們提供了一個(gè)codemod腳本來自動(dòng)化轉(zhuǎn)換。
通過React,可以輕松跟蹤通過React組件的數(shù)據(jù)流。當(dāng)你看一個(gè)組件時(shí),你可以看到哪些道具被傳遞,這使得你的應(yīng)用程序很容易推理。
在某些情況下,您希望通過組件樹傳遞數(shù)據(jù),而不必在每個(gè)級(jí)別手動(dòng)傳遞道具。您可以直接在React中使用強(qiáng)大的“上下文”API執(zhí)行此操作。
絕大多數(shù)應(yīng)用程序不需要使用上下文。
如果你希望你的應(yīng)用程序穩(wěn)定,不要使用上下文。這是一個(gè)實(shí)驗(yàn)性的API,它很可能在未來的React版本中被打破。
如果您不熟悉像Redux或MobX這樣的狀態(tài)管理庫,請(qǐng)不要使用上下文。對(duì)于許多實(shí)際應(yīng)用來說,這些庫和它們的React綁定對(duì)于管理與許多組件相關(guān)的狀態(tài)是一個(gè)很好的選擇。Redux很可能是解決問題的正確解決方案,而不是正確的解決方案。
如果您不是經(jīng)驗(yàn)豐富的React開發(fā)人員,請(qǐng)不要使用上下文。通常只有使用道具和狀態(tài)才能實(shí)現(xiàn)功能。
如果您堅(jiān)持使用上下文而不管這些警告,請(qǐng)嘗試將上下文的使用隔離到一個(gè)小區(qū)域,并盡可能避免直接使用上下文API,以便在API更改時(shí)更容易升級(jí)。
假設(shè)你有一個(gè)像這樣的結(jié)構(gòu):
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>; }}
在這個(gè)例子中,我們手動(dòng)穿過一個(gè)color
道具來適當(dāng)?shù)卦O(shè)計(jì)Button
和Message
組件。使用上下文,我們可以自動(dòng)將它傳遞給樹:
import PropTypes from 'prop-types';class Button extends React.Component { render() { return ( <button style={{background: this.context.color}}> {this.props.children} </button> ); }}Button.contextTypes = { color: 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: PropTypes.string};
通過添加childContextTypes
和getChildContext
到MessageList
(上下文提供),陣營(yíng)傳遞的子樹中向下自動(dòng)信息和任何組分(在這種情況下,Button
)可以通過定義訪問它contextTypes
。
如果contextTypes
沒有定義,那么context
將是一個(gè)空對(duì)象。
Context還可以讓你建立一個(gè)父母和孩子交流的API。例如,以這種方式工作的一個(gè)庫是React Router V4:
import { BrowserRouter as 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>);
通過從經(jīng)過了一些信息Router
部分,每個(gè)Link
和Route
可回傳送到含有Router
。
在使用與此類似的API構(gòu)建組件之前,請(qǐng)考慮是否有更清晰的替代方案。例如,如果您愿意,您可以將整個(gè)React組件作為道具傳遞。
如果contextTypes
在組件內(nèi)定義,則以下生命周期方法將收到附加參數(shù),即context
對(duì)象:
constructor(props, context)
componentWillReceiveProps(nextProps, nextContext)
shouldComponentUpdate(nextProps, nextState, nextContext)
componentWillUpdate(nextProps, nextState, nextContext)
注意:截至React 16,
componentDidUpdate
不再收到prevContext
。
無狀態(tài)的功能組件也可以引用,context
如果contextTypes
被定義為該功能的屬性。以下代碼顯示了一個(gè)Button
寫入無狀態(tài)功能組件的組件。
import PropTypes from 'prop-types';const Button = ({children}, context) => <button style={{background: context.color}}> {children} </button>;Button.contextTypes = {color: PropTypes.string};
不要這樣做。
React有一個(gè)API來更新上下文,但它基本上被打破了,你不應(yīng)該使用它。
getChildContext
功能將在狀態(tài)或道具改變時(shí)被調(diào)用。為了更新上下文中的數(shù)據(jù),使用this.setState
。觸發(fā)本地狀態(tài)更新。這將觸發(fā)一個(gè)新的環(huán)境,并且變化將被孩子接收。
import PropTypes from 'prop-types'; 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: PropTypes.string };
的問題是,如果由組分變化,即使用該值后代提供上下文值將不會(huì)如果中間父返回更新false
從shouldComponentUpdate
。這完全無法控制使用上下文的組件,所以基本上無法可靠地更新上下文。這篇博文很好地解釋了為什么這是一個(gè)問題,以及如何解決這個(gè)問題。