React第十九章(useContext)

useContext

useContext 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。设计的目的就是解决组件树间数据传递的问题。

用法

ts 复制代码
const MyThemeContext = React.createContext({theme: 'light'}); // 创建一个上下文

function MyComponent() {
    const themeContext = useContext(MyThemeContext); // 使用上下文
    return (<div>{themeContext.theme}</div>);
}

参数

入参

  • context:是 createContext 创建出来的对象,他不保持信息,他是信息的载体。声明了可以从组件获取或者给组件提供信息。

返回值

  • 返回传递的Context的值,并且是只读的。如果 context 发生变化,React 会自动重新渲染读取 context 的组件

基本用法

我们编写一个传递主题的例子,

这个hook在18版本和19版本是有区别的。

  • 18版本演示

首先我们先通过createContext创建一个上下文,然后通过createContext创建的组件包裹组件,传递值。

被包裹的组件,在任何一个层级都是可以获取上下文的值,那么如何使用呢?

使用的方式就是通过useContext这个hook,然后传入上下文,就可以获取到上下文的值。

ts 复制代码
import React, { useContext, useState } from 'react';
// 创建上下文
const ThemeContext = React.createContext<ThemeContextType>({} as ThemeContextType);
// 定义上下文类型
interface ThemeContextType {
   theme: string;
   setTheme: (theme: string) => void;
}
const Child = () => {
    // 获取上下文
   const themeContext = useContext(ThemeContext);
   const styles = {
      backgroundColor: themeContext.theme === 'light' ? 'white' : 'black',
      border: '1px solid red',
      width: 100 + 'px',
      height: 100 + 'px',
      color: themeContext.theme === 'light' ? 'black' : 'white'
   }
   return <div>
      <div style={styles}>
         child
      </div>
   </div>
}

const Parent = () => {
    // 获取上下文
   const themeContext = useContext(ThemeContext);
   const styles = {
      backgroundColor: themeContext.theme === 'light' ? 'white' : 'black',
      border: '1px solid red',
      width: 100 + 'px',
      height: 100 + 'px',
      color: themeContext.theme === 'light' ? 'black' : 'white'
   }
   return <div>
      <div style={styles}>
         Parent
      </div>
      <Child />
   </div>
}

function App() {
   const [theme, setTheme] = useState('light');
   return (
      <div>
         <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>切换主题</button>
         <ThemeContext.Provider value={{ theme, setTheme }}>
            <Parent />
         </ThemeContext.Provider>
      </div >
   );
}

export default App;
  • 19版本演示

其实19版本和18版本是差不多的,只是19版本更加简单了,不需要再使用Provider包裹,直接使用即可。

ts 复制代码
import React, { useContext, useState } from 'react';
const ThemeContext = React.createContext<ThemeContextType>({} as ThemeContextType);
interface ThemeContextType {
   theme: string;
   setTheme: (theme: string) => void;
}

const Child = () => {
   const themeContext = useContext(ThemeContext);
   const styles = {
      backgroundColor: themeContext.theme === 'light' ? 'white' : 'black',
      border: '1px solid red',
      width: 100 + 'px',
      height: 100 + 'px',
      color: themeContext.theme === 'light' ? 'black' : 'white'
   }
   return <div>
      <div style={styles}>
         child
      </div>
   </div>
}

const Parent = () => {
   const themeContext = useContext(ThemeContext);
   const styles = {
      backgroundColor: themeContext.theme === 'light' ? 'white' : 'black',
      border: '1px solid red',
      width: 100 + 'px',
      height: 100 + 'px',
      color: themeContext.theme === 'light' ? 'black' : 'white'
   }
   return <div>
      <div style={styles}>
         Parent
      </div>
      <Child />
   </div>
}
function App() {
   const [theme, setTheme] = useState('light');
   return (
      <div>
         <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>切换主题</button>
         <ThemeContext.Provider value={{ theme, setTheme }}> // [!code --]
         <ThemeContext value={{ theme, setTheme }}> // [!code ++]
            <Parent />
         </ThemeContext.Provider> // [!code --]
         <ThemeContext> // [!code ++]
      </div >
   );
}

export default App;

注意事项

  • 使用 ThemeContext 时,传递的key必须为value
html 复制代码
// 🚩 不起作用:prop 应该是"value"
<ThemeContext theme={theme}>
   <Button />
</ThemeContext>
// ✅ 传递 value 作为 prop
<ThemeContext value={theme}>
   <Button />
</ThemeContext>
  • 可以使用多个Context

如果使用多个Context,那么需要注意,如果使用的值是相同的,那么会覆盖。

ts 复制代码
const ThemeContext = React.createContext({theme: 'light'});

function App() {
   return (
      <ThemeContext value={{theme: 'light'}}>
         <ThemeContext value={{theme: 'dark'}}> {/* 覆盖了上面的值 */}
            <Parent />
         </ThemeContext>
      </ThemeContext>
   )
}
相关推荐
颂love7 分钟前
Vue的两大生态以及组件通信
前端·javascript·vue.js·typescript
甜汤圆10 分钟前
Python 里**自定义数据单元**
前端
cidy_9817 分钟前
将 Figma 接入 Codex MCP:从 `/plugins` 到本地插件配置的完整教程
前端
vivo互联网技术18 分钟前
动效开发不踩坑:几种动效实现方案对比与实战选型
前端·性能优化·动效
Csvn20 分钟前
【Vue3】Composition API vs Options API —— 什么场景该选哪个
前端
Csvn21 分钟前
Vue3 迁移血泪史:v-model 的 .sync 陷阱,90% 升级项目都会踩
前端·vue.js
光影少年22 分钟前
js单线程,为什在node环境下的js可以处理高并发请求?
前端·javascript·掘金·金石计划
vim怎么退出35 分钟前
Dive into React——事件系统
前端·react.js·源码阅读
moMo38 分钟前
# JavaScript 的“等等我”:聊聊同步与异步
javascript
KaMeidebaby38 分钟前
卡梅德生物技术快报|重组蛋白的表达和纯化:工艺调试全记录:大肠杆菌体系重组蛋白的表达和纯化参数标定(肠激酶轻链案例)
前端·人工智能·算法·数据挖掘·数据分析