首页 > 其他分享 >react官方文档-高级部分-context学习

react官方文档-高级部分-context学习

时间:2023-01-30 09:14:21浏览次数:48  
标签:React Context react theme 文档 context Provider 组件

前言:想捡回前端开发,还是得重学react语法,很多都忘了,而且好几年过去,语法也发生了很大的变化。

另外,手册只是最基本的介绍,让你知道有这种用法,想深入掌握,还需要在具体点上查资料。

 

Context

Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。

Context 主要应用场景在于很多不同层级的组件需要访问同样一些的数据。请谨慎使用,因为这会使得组件的复用性变差。

如果你只是想避免层层传递一些属性,组件组合(component composition)有时候是一个比 context 更好的解决方案。

相关API:

const MyContext = React.createContext(defaultValue);

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

只有当组件所处的树中没有匹配到 Provider 时,其 defaultValue 参数才会生效。这有助于在不使用 Provider 包装组件的情况下对组件进行测试。注意:将 undefined 传递给 Provider 的 value 时,消费组件的 defaultValue 不会生效。

<MyContext.Provider value={/* 某个值 */}>

每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。

Provider 接收一个 value 属性,传递给消费组件。一个 Provider 可以和多个消费组件有对应关系。多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据。

当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。Provider 及其内部 consumer 组件都不受制于 shouldComponentUpdate 函数,因此当 consumer 组件在其祖先组件退出更新的情况下也能更新。

通过新旧值检测来确定变化,使用了与 Object.is 相同的算法。

MyClass.contextType = MyContext;

Class.contextType。挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。

class MyClass extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* 基于 MyContext 组件的值进行渲染 */
  }
}
MyClass.contextType = MyContext; //这里的MyContext是在最初定义的,例如 const ThemeContext = React.createContext('light');
<MyContext.Consumer>
  {value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>

这里,React 组件也可以订阅到 context 变更。这能让你在函数式组件中完成订阅 context。

const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';
<MyContext.Provider> // "MyDisplayName.Provider" 在 DevTools 中
<MyContext.Consumer> // "MyDisplayName.Consumer" 在 DevTools 中

context 对象接受一个名为 displayName 的 property,类型为字符串。React DevTools 使用该字符串来确定 context 要显示的内容。

示例,上述组件在 DevTools 中将显示为 MyDisplayName:

 

 

具体使用场景:

1,动态context

对于上面的 theme 例子,使用动态值(dynamic values)后更复杂的用法:

 

2,在嵌套组件中更新 Context

从一个在组件树中嵌套很深的组件中更新 context 是很有必要的。在这种场景下,你可以通过 context 传递一个函数,使得 consumers 组件更新 context:

// 文件1:theme-context.js

// 确保传递给 createContext 的默认值数据结构是调用的组件(consumers)所能匹配的!
export const ThemeContext = React.createContext({
  theme: themes.dark,
  toggleTheme: () => {},
});


// 文件2:theme-toggler-button.js

import {ThemeContext} from './theme-context';

function ThemeTogglerButton() {
  // Theme Toggler 按钮不仅仅只获取 theme 值,它也从 context 中获取到一个 toggleTheme 函数
  return (
    <ThemeContext.Consumer>
      {({theme, toggleTheme}) => (
        <button          onClick={toggleTheme}
          style={{backgroundColor: theme.background}}>

          Toggle Theme
        </button>
      )}
    </ThemeContext.Consumer>
  );
}

export default ThemeTogglerButton;


// 主文件3:app.js

import {ThemeContext, themes} from './theme-context';
import ThemeTogglerButton from './theme-toggler-button';

class App extends React.Component {
  constructor(props) {
    super(props);

    this.toggleTheme = () => {
      this.setState(state => ({
        theme:
          state.theme === themes.dark
            ? themes.light
            : themes.dark,
      }));
    };

    // State 也包含了更新函数,因此它会被传递进 context provider。
    this.state = {
      theme: themes.light,
      toggleTheme: this.toggleTheme,
    };
  }

  render() {
    // 整个 state 都被传递进 provider
    return (
      <ThemeContext.Provider value={this.state}>
        <Content />
      </ThemeContext.Provider>
    );
  }
}

function Content() {
  return (
    <div>
      <ThemeTogglerButton />
    </div>
  );
}

ReactDOM.render(<App />, document.root);

在外层用到了<ThemeContext.Provider value={this.state}>,带上了theme和toggleTheme(),包裹Content组件,在Content内层用<ThemeContext.Consumer>,直接使用theme和toggleTheme()

 

3,消费多个 Context
为了确保 context 快速进行重渲染,React 需要使每一个 consumers 组件的 context 在组件树中成为一个单独的节点。

// Theme context,默认的 theme 是 “light” 值
const ThemeContext = React.createContext('light');

// 用户登录 context
const UserContext = React.createContext({
  name: 'Guest',
});

class App extends React.Component {
  render() {
    const {signedInUser, theme} = this.props;

    // 提供初始 context 值的 App 组件
    return (
      <ThemeContext.Provider value={theme}>
        <UserContext.Provider value={signedInUser}>
          <Layout />
        </UserContext.Provider>
      </ThemeContext.Provider>
    );
  }
}

function Layout() {
  return (
    <div>
      <Sidebar />
      <Content />
    </div>
  );
}

// 一个组件可能会消费多个 context
function Content() {
  return (
    <ThemeContext.Consumer>
      {theme => (
        <UserContext.Consumer>
          {user => (
            <ProfilePage user={user} theme={theme} />
          )}
        </UserContext.Consumer>
      )}
    </ThemeContext.Consumer>
  );
}

 

 

如果两个或者更多的 context 值经常被一起使用,那你可能要考虑一下另外创建你自己的渲染组件,以提供这些值。

 

标签:React,Context,react,theme,文档,context,Provider,组件
From: https://www.cnblogs.com/zccst/p/17074279.html

相关文章

  • react+ antd 表格筛选
    表格的筛选事件是在table的onchange中发生的,其选中值在onchange的参数2中,参数1是分页器//应先定义pagination,这一步是为了第一次请求数据时配置pagination相关const......
  • 一文详解如何在基于webpack5的react项目中使用svg
    本文主要讨论基于webpack5+TypeScript的React项目(cra、craco底层本质都是使用webpack,所以同理)在2023年的今天是如何在项目中使用svg资源的。首先,假定您已经完成基于webpac......
  • react组件实例属性props
    propsprops简单使用classPersonextendsReact.Component{render(){return(<ul>......
  • 如何在react中使用bind方法?
    JavaScript自身特性说明如果传递一个函数名给一个变量,之后通过函数名()的方式进行调用,在方法内部如果使用this则this的指向会丢失,为了避免这种情况的出现,我们可以使用bind......
  • Microsoft 365 解决方案:如何使用Embed Web Part显示其他网站某个文档库里的内容
    51CTOBlog链接:​​https://blog.51cto.com/u_13637423 ​​我们都知道当我们新建一个网站的时候,默认网站里只显示存储在本网站里的内容,但如果有用户需求,希望当前网站显......
  • @ContextConfiguration的用法
    @ContextConfiguration的用法在SpringBoot测试@ContextConfiguration这个注解通常与@RunWith(SpringJUnit4ClassRunner.class)联合使用用来测试当一个类添加了注解@Com......
  • Microsoft 365 解决方案:监控重要的文档库或者列表中的数据变更,自动发送邮件提醒
    51CTOBlog链接:​​https://blog.51cto.com/u_13637423​​用过SharePointOnPremise的用户都知道Alert功能,比如文档库中的文档,如果有人变更内容,那么可以通过Alert功能发......
  • React --- jsx语法规则
    jsx语法规则:1、定义虚拟dom时,不要写引号//创建虚拟DOM 1constVDOM=<h1><span>hello,react</span></h1> 2、标签中混入JS表达式时要用{}1//定义属性和标签内容2c......
  • 如何通过Java代码向Word文档添加文档属性
    Word文档属性包括常规、摘要、统计、内容、自定义。其中摘要包括标题、主题、作者、经理、单位、类别、关键词、备注等项目。属性相当于文档的名片,可以添加你想要的注释、说......
  • C++函数文档注释模板
    还是.net好,///就解决了点击查看代码///<summary>///在指定的node结点之后插入新结点,如果node为NULL,表示新结点插在链表第一个结点之前///</summary>///<paramna......