利用context组件数据传递

 react的数据传递 是从父级向子级传递的。通过props。如果是很多组件需要的数据,通过props传递会非常麻烦。这个时候可以使用context。

context需要可以类似于store但是也不能滥用。

react-redux的 <Provider /> ,就是通过 Context 提供一个全局态的 store ,路由组件react-router通过 Context 管理路由状态等等。

context适用场景:地区偏好,UI主题

传统实现:

class App extends React.Component {
  render() {
    return <Toolbar theme="dark" />;
  }
}

function Toolbar(props) {
  // Toolbar 组件接受一个额外的“theme”属性,然后传递给 ThemedButton 组件。
  // 如果应用中每一个单独的按钮都需要知道 theme 的值,这会是件很麻烦的事,
  // 因为必须将这个值层层传递所有组件。
  return (
    <div>
      <ThemedButton theme={props.theme} />
    </div>
  );
}

class ThemedButton extends React.Component {
  render() {
    return <Button theme={this.props.theme} />;
  }
}
View Code

创建context对象

const MyContext = React.createContext(defaultValue);
创建一个context对象。设置默认值。

当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。如果没有Provider就会取默认值。

context.Provider

<MyContext.Provider value={默认值}>

每个context对象都返回一个provider组件 

一个provider组件可以和多个消费组件对应关系。

<ThemeContext.Provider value="dark">
     <Toolbar />
     <ContextTypePage /> //多个组件
</ThemeContext.Provider>

多个provider也可以嵌套,里层会覆盖外层。

import {ThemeContext, UserContext} from "../Context";
export default function UseContextPage(props) {
  const themeContext = useContext(ThemeContext);
  const { themeColor } = themeContext;
  const userContext = useContext(UserContext);
  return (
    <div className="border">
      <h3 className={themeColor}>UseContextPage</h3>
      <p>{userContext.name}</p>
    </div>
  );
}

  

provider值变化 里面所有的消费组件都会渲染。

组件的contextType属性

挂载在 class 上的 contextType 属性会被重赋值为一个 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它。

import {ThemesContext} from './theme-context'

export class ThemedButton extends React.Component{
  render(){
    let props =this.props;
    let theme =this.context;
    console.log(theme)
    return (
      <button
      {...props}
      style={{backgroundColor:theme.background,color:theme.foreground,width:"200px"}}
      />
    )
  }
}
ThemedButton.contextType=ThemesContext;//这个一定要有

简单的例子:

context实现:

// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');
class App extends React.Component {
  render() {
    // 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
    // 无论多深,任何组件都能读取这个值。
    // 在这个例子中,我们将 “dark” 作为当前的值传递下去。
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
          <ContextTypePage /> //多个组件
      </ThemeContext.Provider>
    );
  }
}

// 中间的组件不必指明往下传递 theme 。
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // 指定 contextType 读取当前的 theme context。
  // React 会往上找到最近的 theme Provider,然后使用它的值。
  // 在这个例子中,当前的 theme 值为 “dark”。
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

 

实际应用:

theme-context.js

import React from 'react';
export const themes={
  light:{
    foreground: '#ffffff',
    background:"#4DB8C6"
  },
  dark:{
    foreground: '#ffffff',
    background:"#222222"
  }
}
export const ThemesContext =React.createContext(themes.dark)

themed-button.js

import React from 'react';
import {ThemesContext} from './theme-context'

export class ThemedButton extends React.Component{
  render(){
    let props =this.props;
    let theme =this.context;
    console.log(theme)
    return (
      <button
      {...props}
      style={{backgroundColor:theme.background,color:theme.foreground,width:"200px"}}
      />
    )
  }
}
ThemedButton.contextType=ThemesContext;

app.js

function ToolBar1(props){
  return (
    <ThemedButton onClick={props.changeTheme}>
     主题按钮
    </ThemedButton>
  )
}
class App extends React.Component{
  constructor(props){
    super(props);
    this.state={
      theme:themes.light
    }
    this.toggleTheme = () => {
      this.setState(state => ({
        theme:
          state.theme === themes.dark
            ? themes.light
            : themes.dark,
      }));
      console.log(this.state.theme)
    };
  }
  render (){
    return (
      <ThemesContext.Provider value={this.state.theme}>
      <ToolBar1 changeTheme={this.toggleTheme} />
    </ThemesContext.Provider>
    )
  }
}

 

效果图

 

 

 

 最好实现主题变动的是 改变类名

写两套css样式 根据不同的类名 进行处理。

react官网 https://react.docschina.org/docs/context.html#when-to-use-context

 

posted @ 2022-08-23 17:17  明媚下雨天  阅读(132)  评论(0编辑  收藏  举报