react:usecontext使用

useContext返回 调用组件上方最近的 SomeContext.Provider 的 value

如果没有这样的 provider 传递给 createContext 的 defaultValue。返回的值始终是最新的。

如果 context 发生变化,React 会自动重新渲染读取 context 的组件。

  1. <Context.Provider> 需要位于调用 useContext() 的组件 之上。
  2. 使用 memo 来跳过重新渲染并不妨碍子级接收到新的 context 值。

https://codepen.io/pen?\&editors=001

javascript 复制代码
const { createRoot } = ReactDOM;
const ThemeContext = React.createContext('light'); 
// import { createContext, useContext } from 'react';

const {  Button, Flex  } = antd;

// 由于组件A被放置在了<ThemeContext.Provider value="dark">的范围内,
//它会成功地从上下文中获取到ThemeContext的值。因此,组件A不需要直接传递ThemeContext,并且不会因此而报错。
const A = () => {
  const theme = React.useContext(ThemeContext);
  return <div>123{theme}</div>
}


const App = () => (
  <ThemeContext.Provider value="dark">
  <Flex gap="small" wrap="wrap">
    <Button type="primary">Primary Button</Button>
    <Button>Default Button</Button>
    <Button type="dashed">Dashed Butto1n</Button>
    <Button type="text">Text Button</Button>
    <Button type="link">Link Button</Button>
  
  </Flex>
  <A/>
  </ThemeContext.Provider>
);
const ComponentDemo = App;


createRoot(mountNode).render(<ComponentDemo />);

可以传递对象(通过 context 可以传递任何值)

javascript 复制代码
<CurrentUserContext.Provider
      value={{
        currentUser,
        setCurrentUser
      }}
    >
      <Form />
    </CurrentUserContext.Provider>

可以把把 provider 抽离成组件

javascript 复制代码
<MyProviders theme={theme} setTheme={setTheme}>
      <WelcomePanel />
</MyProviders>

function MyProviders({ children, theme, setTheme }) {
  const [currentUser, setCurrentUser] = useState(null);
  return (
    <ThemeContext.Provider value={theme}>
      <CurrentUserContext.Provider
        value={{
          currentUser,
          setCurrentUser
        }}
      >
        {children}
      </CurrentUserContext.Provider>
    </ThemeContext.Provider>
  );
}

可以同时存在多个content

javascript 复制代码
<ThemeContext.Provider value={theme}>
      <CurrentUserContext.Provider
        value={{
          currentUser,
          setCurrentUser
        }}
      >
        <WelcomePanel />
       </CurrentUserContext.Provider>
    </ThemeContext.Provider>

还可以和useReducer结合使用,在大型项目中

覆盖context

javascript 复制代码
const ThemeContext = createContext(null);

export default function MyApp() {
  return (
    <ThemeContext.Provider value="dark">
      <Form />
    </ThemeContext.Provider>
  )
}

function Form() {
  return (
    <Panel title="Welcome">
      <Button>Sign up</Button>
      <Button>Log in</Button>
      <ThemeContext.Provider value="light">
        <Footer />
      </ThemeContext.Provider>
    </Panel>
  );
}

如果context value是有函数等多个成员时,可以通过useCallback和usememo来优化性能

javascript 复制代码
import { useCallback, useMemo } from 'react';

function MyApp() {
  const [currentUser, setCurrentUser] = useState(null);

  const login = useCallback((response) => {
    storeCredentials(response.credentials);
    setCurrentUser(response.user);
  }, []);

  const contextValue = useMemo(() => ({
    currentUser,
    login
  }), [currentUser, login]);

  return (
    <AuthContext.Provider value={contextValue}>
      <Page />
    </AuthContext.Provider>
  );
}
// 根据以上改变,即使 MyApp 需要重新渲染,调用 useContext(AuthContext) 的组件也不需要重新渲染,
// 除非 currentUser 发生了变化。
相关推荐
FungLeo17 小时前
成为全栈·React 管理后台篇·总复盘:从“接口能调通”到“后台值得使用”
前端·react.js·前端框架·项目复盘·成为全栈
Csvn19 小时前
并发模式:让渲染学会排队、插队和让路
前端
可乐鸡翅yeah_19 小时前
新手梳理:M3U8 线上问题,哪些是前端锅,哪些是后端锅
前端·ios·音视频·实时音视频·m3u8·音视频在线播放
Flynt19 小时前
Linear 用 1000 个 PR 换掉 styled-components,我写了 200 个按钮,把这笔账复现了一遍
前端·css·preact
JavaGuide20 小时前
NVIDIA 又开源了!这次给 AI Agent 加上权限管控
前端·后端
excel20 小时前
prisma 如何处理数据库竞态
前端·数据库·后端
莪_幻尘1 天前
Skill 体检:30 个 Skill 全凭感觉?体检器先自曝了 8 个“假 0 分
前端·人工智能·llm
风骏时光牛马1 天前
AI模型综合能力评测:性能、指令遵循与多场景实测对比
前端
Frag0ut1 天前
Chrome与Chromium内核浏览器在Windows 11上的新特性全景解析
前端·chrome·windows·web安全·chromium·gemini ai·playready drm
hiahiahia1231 天前
实现完整 Tool Dispatcher
开发语言·前端