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