内容简介:Context 的目的是对于全局的需要多处使用的数据,不希望通过 prop 一层层传递下去,而是可以直接使用。该方案在 16.3 后不再是推荐方案。React 最初提供的 context 方案是提供 context 数据的组件通过静态的
Context 的目的是对于全局的需要多处使用的数据,不希望通过 prop 一层层传递下去,而是可以直接使用。
childContextTypes & getChildContext
该方案在 16.3 后不再是推荐方案。
React 最初提供的 context 方案是提供 context 数据的组件通过静态的 childContextType
来定义 context 中各字段的数据类型,通过 getChildContext
成员方法来提供实际的 context 数据,其中,返回的数据可以搭配 prop 和 state 来提供响应式的数据。而消费 context 数据的组件通过静态的 contextTypes
来指定需要消费的 context 字段的类型集合,然后即可通过 this.context[fieldName]
来使用。
注意,消费 context 的组件只需要定义需要的字段的类型即可,不需要是全部。同时,也不需要是提供 context 的组件的直接子组件。
import PropTypes from 'prop-types'; class Button extends React.Component { static contextTypes = { color: PropTypes.string }; render() { return ( <button style={{background: this.context.color}}> {this.props.children} </button> ); } } class Message extends React.Component { render() { return ( <div> {this.props.text} <Button>Delete</Button> </div> ); } } class MessageList extends React.Component { static childContextTypes = { color: PropTypes.string }; getChildContext() { return {color: "purple"}; } render() { const children = this.props.messages.map((message) => <Message text={message.text} /> ); return <div>{children}</div>; } }
Context Provider & Consumer
React 16.3 后提出新的 context 方案 React.createContext(anyInitValue)
,然后使用其提供的 Provider
和 Consumer
来使用。
export const themes = { light: { foreground: '#000000', background: '#eeeeee', }, dark: { foreground: '#ffffff', background: '#222222', }, }; export const ThemeContext = React.createContext({ theme: themes.dark, toggleTheme: () => {}, }); export function ThemeTogglerButton() { // The Theme Toggler Button receives not only the theme // but also a toggleTheme function from the context return ( <ThemeContext.Consumer> {({theme, toggleTheme}) => ( <button onClick={toggleTheme} style={{backgroundColor: theme.background}}> Toggle Theme </button> )} </ThemeContext.Consumer> ); } function Content() { return ( <div> <ThemeTogglerButton /> </div> ); } class App extends React.Component { constructor(props) { super(props); this.toggleTheme = () => { this.setState(state => ({ theme: state.theme === themes.dark ? themes.light : themes.dark, })); }; // State also contains the updater function so it will // be passed down into the context provider this.state = { theme: themes.light, toggleTheme: this.toggleTheme, }; } render() { // The entire state is passed to the provider return ( <ThemeContext.Provider value={this.state}> <Content /> </ThemeContext.Provider> ); } }
这种方案可以同时使用多个 context(provider 和 consumer 都可以作为普通标签来嵌套使用),并且可以使用 react-adopt 之类的库来解决 consumer 过多嵌套的问题。
// Theme context, default to light theme const ThemeContext = React.createContext('light'); // Signed-in user context const UserContext = React.createContext({ name: 'Guest' }); class App extends React.Component { state = { signedInUser: { name: 'Joe' }, theme: 'dark' }; render() { const { signedInUser, theme } = this.state; return ( <ThemeContext.Provider value={theme}> <UserContext.Provider value={signedInUser}> <Content /> <hr /> <Content2 /> </UserContext.Provider> </ThemeContext.Provider> ); } } function Content() { return ( <ThemeContext.Consumer> {theme => ( <UserContext.Consumer> {user => ( <div> <div>user: {user.name}</div> <div>theme: {theme}</div> </div> )} </UserContext.Consumer> )} </ThemeContext.Consumer> ); } // 组合来简化 consumer 的嵌套 const ComposeConsumer = adopt({ theme: <ThemeContext.Consumer />, user: <UserContext.Consumer /> }); function Content2() { return ( <ComposeConsumer> {({ theme, user }) => ( <div> <div>user: {user.name}</div> <div>theme: {theme}</div> </div> )} </ComposeConsumer> ); }
contextType
Provider / Consumer 形式的 context,在 class 组件中使用时,初期只能在 render 系列的方法中才能使用。在 16.6.0 时添加了 contextType
来方便 class 组件在 全生命周期
内使用。
具体来说是通过静态的 contextType 指向创建成的 context,然后内部可以使用 this.context
来直接消费 context。
需要注意的是,这种形式只能消费一个 context,别的 context 还是需要通过 consumer 的形式来消费,并且 this.context 是 provider 提供的值。
const ThemeContext = React.createContext('light'); class App extends React.Component { state = { theme: 'dark' }; render() { const { theme } = this.state; return ( <ThemeContext.Provider value={theme}> <SingleCtx /> </ThemeContext.Provider> ); } } class SingleCtx extends React.Component { static contextType = ThemeContext; render() { return ( <div> {this.context} </div> ); } }
Context Hook
useContext(createdContext)
是将在 16.7 引入的 context hook,便于在无状态组件中消费 createContext
创建的 context。使用语法上比 Consumer 的简单很多,能直接使用普通的语法而不需要使用 render prop 的语法。
function App() { const theme = useContext(ThemeContext) const language = useContext(LanguageContext) return <div>{theme} and {language}</div> }
参考
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Linux命令行大全
绍茨 (William E.Shotts) / 郭光伟、郝记生 / 人民邮电出版社 / 2013-3-1 / 69.00元
《Linux命令行大全》主要介绍Linux命令行的使用,循序渐进,深入浅出,引导读者全面掌握命令行的使用方法。 《Linux命令行大全》分为四部分。第一部分开始了对命令行基本语言的学习之旅,包括命令结构、文件系统的导引、命令行的编辑以及关于命令的帮助系统和使用手册。第二部分主要讲述配置文件的编辑,用于计算机操作的命令行控制。第三部分讲述了从命令行开始执行的常规任务。类UNIX操作系统,比如L......一起来看看 《Linux命令行大全》 这本书的介绍吧!