美文网首页
React Context Hook之useContext

React Context Hook之useContext

作者: 米诺zuo | 来源:发表于2023-10-29 19:20 被阅读0次

Context允许组件从远程父级接收信息,而无需将其作为 props 传递。 例如,Application的顶级组件可以将当前的 UI 主题传递给下面的所有组件,无论有多深。

const value = useContext(SomeContext)

定义

useContext(SomeContext)

在组件的最上层调用useContext订阅和读取context.

参数

返回值

useContext 返回调用组件的Context值, 它被确定为传递给树中调用组件上方最接近的“SomeContext.Provider”的“值”。如果没有这样的Provider,则返回的值将是传递给该上下文的 createContextdefaultValue。 返回的值始终是最新的。 如果Context发生变化,React 会自动重新渲染读取某些Context的组件。

用法

1.将数据深入传递到树中

注意:
Form 拿到的值是light,因为最近的cotext就是默认值。
Panel拿到的值是dark,因为最近的cotext是from提供的dark

import { useContext, createContext } from "react";

const ThemeContext = createContext("light");

export function ContextDemo() {
    return <span>context  <Form></Form></span>
}

function Form() {
    const theme = useContext(ThemeContext);  //取初始值light
    return <ThemeContext.Provider value="drak"><button>form {theme}<Panel></Panel></button>
    </ThemeContext.Provider>
}

function Panel() {
    const theme = useContext(ThemeContext);
    return <div>panel {theme}</div>
}
image.png

2.通过改变context更新值

更新上面的Form组件

function Form() {
    // const theme = useContext(ThemeContext);
    const [theme, setTheme] = useState("form-light");
    return <ThemeContext.Provider value={theme}><button onClick={() => { setTheme("dark") }}>form  Switch to {theme}<Panel></Panel></button>
    </ThemeContext.Provider>
}

image.png

3.通过Context更新object,使用useState,来改变context value的值。

import { useContext, createContext, useState } from "react";

const CurrentUserContext = createContext({
  currentUser: "Tom",
  setCurrentUser: (currentUser: string) => {},
});

export function ContextDemo() {
  const [currentUser, setCurrentUser] = useState("lisa");
  return (
    <CurrentUserContext.Provider value={{ currentUser, setCurrentUser }}>
      <span>
        context <Form></Form>
      </span>
    </CurrentUserContext.Provider>
  );
}

function Form() {
  return       <Panel></Panel>;
}

function Panel() {
  const { currentUser, setCurrentUser } = useContext(CurrentUserContext);
  return (
    <div
      onClick={() => {
        setCurrentUser("layor");
      }}
    >
      {" "}
      panel  {currentUser}
    </div>
  );
}

4.提取组件中的provider


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

使用provider

function Form() {
  const [theme, setTheme] = useState("form-light");
  return (
    <MyProviders theme={theme} setTheme={setTheme}>
      <button
        onClick={() => {
          setTheme("dark");
        }}
      >
        form Switch to {theme}
      </button>
      <Panel></Panel>
 
    </MyProviders>
  );
}

5.优化传递对象和函数时的重新渲染

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 已更改。

遇到的问题

// 🚩 Doesn't work: no value prop
<ThemeContext.Provider>
   <Button />
</ThemeContext.Provider>
// 🚩 Doesn't work: prop should be called "value"
<ThemeContext.Provider theme={theme}>
   <Button />
</ThemeContext.Provider>

好了,那我们的useContext到这里就结束了。

宝子们可以收藏评论交流哦

相关文章

网友评论

      本文标题:React Context Hook之useContext

      本文链接:https://www.haomeiwen.com/subject/jgcsidtx.html