03 Context

【skynet源码阅读系列】03_skynet_context_new 上一节看了skynet_start() 的一部分代码,那部分代码主要做了下面几件事。 如果当前进程收到 SIGHUP 信号,则调用 handle_hup 函数,将 SIG 设为 1 检查配置文件内的 deamon 配置,这个配置对应一个文件路径,文件内的记录进程的pid号,防止重复启动skynet进程,第一次启动将自动将进程号写入文件。 重定向了文件描述符,把文件描述符0,1,2 重定向到了 /dev/null,相当于当前进程忽略了标准输入,标准输出,标准错误。 初始化了 HARBOR 的值,HARBO 阅读详情

简要介绍

在典型的React应用中,数据是通过props属性自上而下(由父及子)进行传递的
但这种做法对于类似地区偏好,UI主题等全局共享的属性而言是极其繁琐的,这类属性在应用中会被许多组件使用
Context提供了一种在组件之间共享此类值的方式,而无需逐层传递props


何时使用

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

// Class组件使用Context
const ThemeContext = React.createContext('light')

class App extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value='dark'>
        <Toolbar />
      </ThemeContext.Provider>
    )
  }
}
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  )
}
class ThemedButton extends React.Component {
  static contextType = ThemeContext
  render() {
    return <Button theme={this.context}>
  }
}

你也许不需要Context

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

如果只是想避免层层传递一些属性(某个深嵌组件需要使用某个属性),组件组合(Component Compostion)是个比context更好的解决方案。

例如,你有一个Page组件,它层层向下传递user和avatarSize属性,从而深度嵌套的Link和Avatar组件可以使用这些属性

<Page user={user} avatarSize={avatarSize} />
// ...子组件...
<PageLayout user={user} avatarSize={avatarSize} />
// ...子组件...
<NavigationBar user={user} avatarSize={avatarSize} />
// ...子组件...
<NavigationBar user={user} avatarSize={avatarSize} />
// ...渲染出...
<Link href={user.permalink}>
  <Avatar user={user} size={avatarSize}>
</Link>

像上面这种最终只有Avatar组件真的需要user和avatarSize属性的,那么层层传递这两个props就显得非常冗余,而且一旦Avatar组件需要更多来自顶层组件的props,你还要在中间层一个个加上去,非常麻烦。

一种无需Context的方法就是使用“组件组合”:将Avatar组件自身传递下去,因而中间件无需知道user或者avatarSize等props

function Page(props) {
  const user = props.user
  const userLink = (
    <Link href={user.permalink}>
      <Avatar user={user} size={avatarSize} />
    </Link>
  )
  return <PageLayout userLink={userLink} />
}
<Page user={user} avatarSize={avatarSize} />
<PageLayout userLink={...}>
<NavigationBar userLink={...}>
{props.userLink}

并且组件不限制接受子组件的个数,你可以像“组件组合”中说的那样为子组件封装多个单独的接口(slots)

function Page(props) {
  const user = props.user
  const content = <Feed user={user} />
  const topBar = (
    <NavigationBar>
      <Link href={user.permalink}>
        <Avatar user={user} size={avatarSize} />
      </Link>
    </NavigationBar>
  )
  return (
    <PageLayout
      topBar={topBar}
      content={content}
    />
  )
}

“组件组合”模式已经可以覆盖大多场景了,但如果子组件在渲染前需要和父组件进行交互,你可以进一步使用render props

优点:

  • 减少了组件中传递的props数量
  • 代码更加简洁干净

缺点:

  • 这种将逻辑提升到组件树更高层会使高层组件复杂

API

React.createContext

const MyContext = React.createContext(defaultValue)

上述语句创建了一个Context对象,当组件A订阅了这个Context时,A会从组件树中距离自身最近的那个匹配的Provider中读取当前context值

只有当组件所处的树中没有匹配到Provider时,defaultValue才会生效。这有助于在不适用Provider包装组件的情况下对组件进行测试。若将undefined传递给Provider的value,consumer组件的defaultValue不会生效。

Context.Provider

每个Context对象都会返回一个Provider组件,它允许Consumer组件订阅Context的变化
Provider接收一个value属性,传递给Consumer组件,一个Provider可以和多个Consumer组件有对应关系。多个Provider也可以嵌套使用,里层的会覆盖外层的数据。

当Provider的value值变化时,其内部所有Consumer组件都会重新渲染。
Provider及其内部Consumer组件不受制于shouldComponentUpdate函数
因此Consumer组件在其祖先节点退出更新时也可以更新

新旧值检测使用了Object.is相同的算法
当value是对象时,可能会倒置一些问题,详见官网

Context.Consumer

<MyContext.Consumer>
  {value => (
    /* something here...*/
  )}
</MyContext.Consumer>

上述是通过function as a child做法让函数式组件订阅Context.
这个函数接收当前的Context值返回一个React元素,value等于Provider的value

Context.displayName

const MyContext = React.createContext(defaultValue)
MyContext.displayName = 'DemoContext'

如上,context对象接受一个String类型、名为displayName的property,用以在React DevTools中显示。

Class.contextType

class Demo 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 value进行渲染 */
  }
}
Demo.contextType = MyContext

挂载在class上的contextType属性会被重新赋值为context对象
这让你可以使用this.context来读取context的值,你可以在任何声明周期内访问它。

如果你在使用 public class fields 语法,可以使用 static 初始化 contextType

class Demo extends React.Component {
  static contextType = MyContext
  render() {
    let value = this.context
    /* 基于value渲染 */
  }
}

嵌套组件中更新Context

想要在嵌套很深的组件中欧更新context,只需要通过context传递一个函数,深嵌组件即可调用函数更新context

export const ThemeContext = React.createContext({
  theme: themes.dark,
  toggleTheme: () => {}
})

function ThemeBtn() {
  return (
    <ThemeContext.Consumer>
      {({theme, toggleTheme}) => (
        <button onClick={toggleTheme} style={{backgroundColor: theme.background}}>
          Toggle Theme
        </button>
      )}
    </ThemeContext.Consumer>
  )
}

示例见myapp>src>components>context


使用多个Context

const ThemeContext = React.createContext('light')
const UserContext = React.createContext({
  name: 'Guest'
})

class App extends React.Component {
  render() {
    const {signedInUser, theme} = this.props
    // 提供初始 Context 值的 App 组件
    return (
      <ThemeContext.Provider>
        <UserContext.Provider>
          <Layout />
        </UserContext.Provider>
      </ThemeContext.Provider>
    )
  }
}

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

function Content() {
  return (
    <ThemeContext.Consumer>
      {theme => (
        <UserContext.Consumer>
          {user => (
            <ProfilePage user={user} theme={theme} />
          )}
        </UserContext.Consumer>
      )}
    </ThemeContext.Consumer>
  )
}

示例见myapp>src>components>context

若两个或者多个context值经常一起使用,就要考虑另外创建一个渲染组件来提供该值。


注意事项

context使用参考标识(reference identity)来决定何时进行渲染,这种做法可能会造成如下问题:
当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)
    this.state = {
      value: {something: 'something'}
    }
  }
  render() {
    <MyContext.Provider value={this.state.value}>
      <ToolBar />
    </MyContext.Provider>
  }
}

示例见myapp>src>components>context

PostgreSQL+PostGIS空间数据入库实战:从矢量栅格到GeoServer发布全流程 本文详细介绍了将矢量与栅格空间数据导入PostgreSQL并利用PostGIS扩展进行管理的完整流程。内容涵盖环境搭建、使用shp2pgsql和raster2pgsql工具进行数据入库、基础空间查询验证,以及最终通过GeoServer发布为地图服务的实战步骤,为构建空间数据平台提供清晰指引。 阅读详情

相关推荐

大语言模型在构建UNSPSC 分类数据中的应用

UNSPSC 是联合国标准产品和服务代码。本文研究如何利用大语言模型生成分类系统的分析

姚家湾博客 1847

React解密:React Hooks函数之useContext

useContext函数是React Hooks三大基础hooks函数之一。话不多说,我们先来看用法: const value = useContext(MyContext); 接收一个 context 对象(React.createContext的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的<MyContext.Provider>的valueprop 决定。当组件上层最近的<MyContext.Provider&...

lee前端技术站 2377

Simulink单相桥式有源逆变电路仿真:从器件选型到波形分析(MATLAB 2018a实战)

本文基于MATLAB 2018a的Simulink平台,详细演示了单相桥式有源逆变电路的完整仿真流程。从Simscape/Power Systems库的器件选型、参数配置,到触发脉冲设置与电路连接,逐步指导搭建仿真模型。通过调整触发角α,直观展示了电路从整流到有源逆变的工作状态切换,并深入分析了负载电压、电流波形,以及逆变颠覆现象的产生条件与特征。

cake8的博客 1159

Context组件通信

Context的使用:1、引入Context文件castScreen定义的变量值contextId2、在castScreen文件中定义静态值作为context变量3、在源文件中使用useState作为存储值的状态管理4、在return的html中加入Provider的外壳,value即为useState中定义的变量和set函数5、在子组件中进行context引入,例如使用type//先引入castScreen文件//利用context实现组件共享数据,分享当前menu选值。

weixin_52018902的博客 129

手把手复现金蝶云星空V8.1文件上传漏洞(附完整POC与修复方案)

本文深度解析金蝶云星空V8.1文件上传漏洞,提供详细的漏洞复现步骤与完整POC,涵盖技术原理、测试环境搭建及验证流程。同时给出多维防护方案,包括官方补丁部署、临时缓解措施和长期安全加固建议,帮助企业有效防范任意文件上传风险。

weixin_30505225的博客 178

使用 Python 爬取 YouTube 视频评论(弹幕)

✅ 如何使用 Python 调用 YouTube Data API v3。✅ 如何爬取指定视频的所有评论信息。✅ 如何对评论数据进行初步分析与可视化。✅ 如何扩展功能,实现评论回复获取和多视频批量爬取。

2201_76125261的博客 643

React高级指引之Context学习与使用

React Context的使用

九月萩的博客 341

IP-Guard安全网关实例

企业相关情况: 1.OA系统,主要为日常工作使用,该系统IP为192.168.1.2,端口为8080; 2.文件共享服务器,用于存放日常工作资料和文档,该文件共享服务器的IP为192.168.1.1,其中\\192.168.1.1\private 目录中的存放着公司重要文档,不能随意外传; 3.安全网关已采用串联的方式联入网络,IP为192.168.2.6,所有机器访问OA系统和文件共享服务...

IP-Guard专栏 705

react面试之context的value变化时,内部所有子组件是否变化

为了解决父组件state更新,而导致子组件更新,我们需要给ABC三个组件的export default加上memo方法,第二个参数为PropsAreEqual,直接让他返回true。是因为他们共同使用了一个context,而他的value是一个对象,每次都会重新生成一个新的对象,所以导致B组件以为context更新了,所以他就会触发渲染了。此时更新a的值,并不会影响BD组件,只有A组件会更新。同时,更新b的值,也不会触发A组件的更新,只有BD更新。答案是不会,ABD都更新了,C没有更新。

qq_28992047的博客 2356

SOME/IP协议详解「1.1·面向服务与面向信号」

面向信号和面向服务的区别,和举例子

雪云飞星的博客 5652

RAGFlow 系列教程 第14课:GraphRAG -- 知识图谱增强检索

RAGFlow v0.25.0深度解读了GraphRAG技术,通过构建知识图谱解决传统RAG在多跳推理问题上的局限。系统支持General GraphRAG和Light GraphRAG两种实现,包含四阶段构建流程:实体关系抽取、实体消解、社区检测和图持久化。核心代码位于rag/graphrag目录,采用LLM驱动的抽取机制,结合编辑距离和LLM确认的实体消解策略,以及Leiden社区检测算法。KGSearch模块通过多信号融合检索(实体+关系+N-hop+社区)实现高效查询。该系统将非结构化文本转化为可推

weixin_43674738的博客 101

react新更新的context传递数据

看到网上都是老版的context,发一篇最新的context的使用及小例子。 Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。在一个典型的 React 应用中,数据是通过 props 属性由上向下(由父及子)的进行传递的,但这对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI主题),这是应用程序中许多组件都所需要的。 Contex...

架构师的成长之路 3776

一文读懂 STAR-CCM+:多物理场仿真王者,从入门到精通全攻略(附实战路线)

STAR-CCM+是西门子旗下的多物理场仿真平台,集流体、传热、结构、电磁等耦合求解于一体。其核心优势包括:全自动网格处理技术(支持十亿级网格)、多物理场无缝耦合、CPU/GPU并行加速计算、流程自动化与设计探索等。广泛应用于汽车(空气动力学优化、电池热管理)、航空航天(气动设计、发动机仿真)、能源(风电叶片流固耦合)、电子(芯片散热)等行业。相比ANSYS Fluent和OpenFOAM,STAR-CCM+在多物理场耦合和复杂几何处理方面更具优势,适合工业级高精度仿真需求。学习路径建议从基础操作入手,逐步

源代码杀手的博客 337

golang并发 03-context

context多线程并发神器

qq_44981657的博客 635

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

03-react的context

为什么要采用context 公共信息(语言、主题)如何传递给每个组件? 用props太繁琐 用redux小题大做

qq_42638033的博客 132

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

03 - Context 与 Context Window:大模型的“临时记忆“

讲了agent的原理之一,上下文的记忆等等

2603_95397518的博客 523

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【Go context解惑】03 原理:深入源码,揭秘 context 的“树”与“信号”

包的内部,彻底揭开这些谜底。放心,我们不会逐行去啃食晦涩的源码,而是会抓住核心数据结构和关键函数,并借助清晰的示意图,让你对。但是,一个有追求的工程师,绝不会满足于只做一个 API 的调用者。在前两讲中,我们已经完成了从“痛苦挣扎”到“熟练使用”的转变。准备好迎接你的又一个“啊哈!函数时,那个取消信号是如何像“多米诺骨牌”一样,精确无误地。背后隐藏着什么魔法,能让我们如此方便地捕获到取消事件?的工作原理建立起一个直观且深刻的心智模型。今天,我们将化身“源码侦探”,一起潜入。大家好,我是Tony Bai。

TonyBai 210

How to Use the Docker Context Command

#Docker context

yuguo_im的博客 660

React(react18)中组件通信03——简单使用 Context 深层传递参数

React(react18)中组件通信03——简单使用 Context 深层传递参数

@素素~的博客 1310

gin context和官方context_Gin框架系列03:换个姿势理解中间件

什么是中间件 中间件,英译middleware,顾名思义,放在中间的物件,那么放在谁中间呢?本来,客户端可以直接请求到服务端接口。 现在,中间件横插一脚,它能在请求到达接口之前拦截请求,做一些特殊处理,比如日志记录,故障处理等。这就是今天要讲述的中间件,那么,它在Gin框架中是怎么使用的呢? 如何使用中间件 我们来看一下逢gin必调的方法Default,方法中有一个变量engine,它Use了...

weixin_33512961的博客 342

03Go并发编程(九) 深入理解 Context go进阶

03Go并发编程(九) 深入理解 Context

weixin_38805083的博客 156

03-状态管理与路由——01-Context + useReducer 模式

本文介绍了React中Context + useReducer状态管理模式。首先分析了状态管理的必要性,特别针对Props Drilling问题,对比了不同解决方案的优缺点。然后详细讲解了Context + useReducer的实现方式,包括创建Context、定义Reducer、使用Provider组件等核心步骤,并提供了Todo应用实战示例。最后提出了通过拆分Context和使用useMemo进行性能优化的建议。这种模式适合中小型应用,能有效解决组件间状态共享问题,是轻量级的状态管理解决方案。

云聚子、物合子、智集子、幻拢子、数汇子 此为 五味子 127

组件通信03 -----context(祖孙通信)

一. content 适用于祖孙通信,多个组件通信 context.js import React from 'react'; // 创建Context 并且导出Consumer, Provide export const {Consumer, Provider} = React.createContext(null); 父组件 import React, { Component } from 'react'; import Son from "./Son"; import {Provider} from

m0_37931969的博客 134

NLP 学习笔记 03 (Probabilistic Context-Free Grammars (PCFGs))

最近一周有些拖沓,静下来把第3,4周的笔记写了 这两周的主题都是PCFGs,不过从浅到深,逐层深化罢了,所以题目就用Probabilistic Context-Free Grammars (PCFGs)了 1.Introduction          ----------------------------------------------------------------------

DarkScope从这里开始 6429

React学习03(组件之间通信,子传父,实现插槽,跨组件通信运用context来实现)

如下代码,在子组件constructor中并没有传递props,但是在render函数中并没有报错,这是为什么呢?原来是react帮助我们添加了一层容错机制,通过createElement将props进行了隐式绑定。 import React, { Component } from 'react'; class ChildCpn extends Component { constructor() { super(); } componentWillMount() { } .

sinat_36048532的博客 354

NLP 学习笔记 03 Probabilistic Context-Free Grammars PCFGs

NLP 学习笔记 03 Probabilistic Context-Free Grammars PCFGs

qq_44943626的博客 463
上一篇: 02 Code-Splitting
下一篇: 04 Error Boundaries
zyan_cn
博客等级 码龄9年 4粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值