您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

react中context是什么

2025/11/12 13:50:14发布40次查看
在react中,context是一个无需为每层组件手动添加props就能在组件树之间进行数据传递的方法;context提供了一种在组件之间共享指定值的方式,而且不必显式的通过组件树的逐层传递props。
本教程操作环境:windows10系统、react17.0.1版、dell g3电脑。
react中context是什么context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。在一个典型的 react 应用中,数据是通过 props 属性自上而下(由父及子)进行传递的,但这种做法对于某些类型的属性而言是极其繁琐的(例如:地区偏好,ui 主题),这些属性是应用程序中许多组件都需要的。context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。
context 什么时候用?context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。举个例子,在下面的代码中,我们通过一个 “theme” 属性手动调整一个按钮组件的样式
class app extends react.component {  render() {    return <toolbar theme="dark" />;  }}function toolbar(props) {  // toolbar 组件接受一个额外的“theme”属性,然后传递给 themedbutton 组件。  // 如果应用中每一个单独的按钮都需要知道 theme 的值,这会是件很麻烦的事,  // 因为必须将这个值层层传递所有组件。  return (    <p>      <themedbutton theme={props.theme} />    </p>  );}class themedbutton extends react.component {  render() {    return <button theme={this.props.theme} />;  }}// 通过props传递:app -> toolbar -> themedbutton// 如果嵌套很深,那么需要逐层传递props,即使中间不需要该props,显得很繁琐
使用 context, 我们可以避免通过中间元素传递 props
// context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。// 为当前的 theme 创建一个 context(light为默认值)。const themecontext = react.createcontext('light');class app extends react.component {  render() {    // 使用一个 provider 来将当前的 theme 传递给以下的组件树。    // 无论多深,任何组件都能读取这个值。    // 在这个例子中,我们将 “dark” 作为当前的值传递下去。    return (      <themecontext.provider value="dark">        <toolbar />      </themecontext.provider>    );  }}// 中间的组件再也不必指明往下传递 theme 了。function toolbar() {  return (    <p>      <themedbutton />    </p>  );}class themedbutton extends react.component {  // 指定 contexttype 读取当前的 theme context。  // react 会往上找到最近的 theme provider,然后使用它的值。  // 在这个例子中,当前的 theme 值为 “dark”。  static contexttype = themecontext;  render() {    return <button theme={this.context} />;  }}// 也可以使用 themedbutto.contexttype = themecontext;
api介绍react.createcontextconst mycontext = react.createcontext(defaultvalue);
创建一个 context 对象。当 react 渲染一个订阅了这个 context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 provider 中读取到当前的 context 值。
只有当组件所处的树中没有匹配到 provider 时,其 defaultvalue 参数才会生效。这有助于在不使用 provider 包装组件的情况下对组件进行测试。注意:将 undefined 传递给 provider 的 value 时,消费组件的 defaultvalue 不会生效。
context.provider<mycontext.provider value={/* 某个值 */}>
每个 context 对象都会返回一个 provider react 组件,它允许消费组件订阅 context 的变化。
provider 接收一个 value 属性,传递给消费组件。一个 provider 可以和多个消费组件有对应关系。多个 provider 也可以嵌套使用,里层的会覆盖外层的数据。
当 provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。provider 及其内部 consumer 组件都不受制于 shouldcomponentupdate 函数,因此当 consumer 组件在其祖先组件退出更新的情况下也能更新。
class.contexttype挂载在 class 上的 contexttype 属性会被重赋值为一个由 react.createcontext() 创建的 context 对象。这能让你使用 this.context 来消费最近 context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中
import mycontext from './mycontext';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 组件的值进行渲染 */  }  // 或者如上边例子一样使用 static contexttype = mycontext;}myclass.contexttype = mycontext;
context.consumerimport mycontext from './mycontext';function toollist() {  return (    <mycontext.consumer {value => /* 基于 context 值进行渲染*/}    </mycontext.consumer>  )}
这里,react 组件也可以订阅到 context 变更。这能让你在函数式组件中完成订阅 context。
这需要函数作为子元素(function as a child)这种做法。这个函数接收当前的 context 值,返回一个 react 节点。传递给函数的 value 值等同于往上组件树离这个 context 最近的 provider 提供的 value 值。如果没有对应的 provider,value 参数等同于传递给 createcontext() 的 defaultvalue。
context.displaynamecontext 对象接受一个名为 displayname 的 property,类型为字符串。react devtools 使用该字符串来确定 context 要显示的内容。
如下述组件在 devtools 中将显示为 mydisplayname
const mycontext = react.createcontext(/* some value */);mycontext.displayname = 'mydisplayname';<mycontext.provider>   // mydisplayname.provider 在 devtools 中<mycontext.consumer>   // mydisplayname.consumer 在 devtools 中
示例动态 context对于上面的 theme 例子,使用动态值(dynamic values)后更复杂的用法
theme-context.js
export const themes = {  light: {    foreground: '#000000',    background: '#eeeeee',  },  dark: {    foreground: '#ffffff',    background: '#222222',  },};export const themecontext = react.createcontext(themes.dark);   // 该处为默认值
themed-button.js
import { themecontext } from './theme-context';class themedbutton extends react.component {  render() {    let props = this.props;    // 获取到themecontext中的默认值    let theme = this.context;    return (      <button {...props} style={{backgroundcolor: theme.background}} />    );  }  // static contexttype = themecontext;}themedbutton.contexttype = themecontext;export default themedbutton;
app.js
import { themecontext, themes } from './theme-context';import themedbutton from './themed-button';// 一个使用 themedbutton 的中间组件function toolbar(props) {  return (    <themedbutton onclick={props.changetheme}>      change theme    </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,      }));    };  }  render() {    // 在 themeprovider 内部的 themedbutton 按钮组件使用 state 中的 theme 值,    // 而外部的组件使用默认的 theme 值    return (      <page>        <themecontext.provider value={this.state.theme}>          <toolbar changetheme={this.toggletheme} />        </themecontext.provider>        <section>          <themedbutton />        </section>      </page>    );  }}reactdom.render(<app />, document.root);// 使用themecontext.provider包裹的组件,可以消费到themecontext中的value// 即toolbar、themedbutton中都可以使用this.context来获取到value// 注意观察,更新state的方法是通过props向下传递,由子孙组件触发更新,下面会讲到通过context的方式传递更新函数
在嵌套组件中更新 context在上面的例子中,我们通过 props 的方式向下传递一个更新函数,从而改变 app 中 themes 的值。我们知道,从一个在组件树中嵌套很深的组件中更新 context 是很有必要的。在这种场景下,你可以通过 context 传递一个函数,使得 consumers 组件更新 context
theme-context.js
// 确保传递给 createcontext 的默认值数据结构是调用的组件(consumers)所能匹配的!export const themecontext = react.createcontext({  theme: themes.dark,  toggletheme: () => {},   // 定义更新主题的方法,向下传递});
theme-toggler-button.js
import { themecontext } from './theme-context';function themetogglerbutton() {  // theme toggler 按钮不仅仅只获取 theme 值,它也从 context 中获取到一个 toggletheme 函数(下面app.js部分)  return (    <themecontext.consumer>      {({theme, toggletheme}) => (        <button onclick={toggletheme} style={{backgroundcolor: theme.background}}>          toggle theme        </button>      )}    </themecontext.consumer>  );}export default themetogglerbutton;
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,   // 定义更新函数,通过context方式向下传递    };  }  render() {    // 整个 state 都被传递进 provider    return (      <themecontext.provider value={this.state}>        <content />      </themecontext.provider>    );  }}function content() {  return (    <p>      <themetogglerbutton />    </p>  );}reactdom.render(<app />, document.root);
消费多个 context为了确保 context 快速进行重渲染,react 需要使每一个 consumers 组件的 context 在组件树中成为一个单独的节点
// theme context,默认的 theme 是 light 值const themecontext = react.createcontext('light');// 用户登录 contextconst 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 (    <p>      <sidebar />      <content />    </p>  );}// 一个组件可能会消费多个 contextfunction content() {  return (    <themecontext.consumer>      {theme => (        <usercontext.consumer>          {user => (            <profilepage user={user} theme={theme} />          )}        </usercontext.consumer>      )}    </themecontext.consumer>  );}
如果两个或者更多的 context 值经常被一起使用,那你可能要考虑一下另外创建你自己的渲染组件,以提供这些值。
注意事项因为 context 会使用参考标识(reference identity)来决定何时进行渲染,这里可能会有一些陷阱,当 provider 的父组件进行重渲染时,可能会在 consumers 组件中触发意外的渲染。举个例子,当每一次 provider 重渲染时,以下的代码会重渲染所有下面的 consumers 组件,因为 value 属性总是被赋值为新的对象
class app extends react.component {  render() {    return (      <mycontext.provider value={{something: 'something'}}>        <toolbar />      </mycontext.provider>    );  }}
为了防止这种情况,将 value 状态提升到父节点的 state 里
class app extends react.component {  constructor(props) {    super(props);    // 多次渲染,state 会被保留,当value不变时,下面的 consumers 组件不会重新渲染     this.state = {      value: {something: 'something'},    };  }  render() {    return (      <provider value={this.state.value}>        <toolbar />      </provider>    );  }}
【相关推荐:javascript视频教程、web前端】
以上就是react中context是什么的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product