hook中useContext到底怎么用

发布于:2024-05-18 ⋅ 阅读:(150) ⋅ 点赞:(0)

语法:

somecontext = createContext(defaultValue);

作用: 避免了组件嵌套太深, 顶层变量层层传递的麻烦.

如何消费顶层数据

第一步: 用createContext声明一个context上下文变量

import { createContext } from 'react';

export const GlobalContext = createContext({} as any);

● 参数defaultValue: 如果在组件的顶层树没有匹配到context Provider,就会使用defaultValue,它是静态的并且永远不会被改变. 如果你没有什么特别想声明的默认值, 写个null就行.
● 返回值: 返回一个context对象, 它本身不带有任何信息,它代表了其他组件可以提供和读取的上下文.生成的context对象有两个属性,分别是:
○ context.Provider: 让你用来给组件们提供context变量
○ context.Consumer: 另一种比较少用的, 用来消费context变量的方法( useContext出现之前的一种老的读取context的方法, 不推荐使用, 现在推荐用useContext )

第二步: 用context.Provider给下层组件传递要消费的值
像下面这样, 将你的子组件用context.Provider包裹, 并通过value向内部所有的组件们提供可用的值,

const globalData = Object.assign({},  {
    mydata,
}

const [globalStore, dispatch] = useReducer(
  useCallback((preState, patchValue) => {
    return { ...preState, ...patchValue };
  }, []),
  globalData,
);

function App(){
 return (
   <GlobalContext.Provider
    value={{ globalStore}}
    	<OtherComponents/>
    </GlobalContext.Provider>
 )
}

第三步: 用useContext消费顶层树提供的数据
所有子组件就可以通过调用usecontext(ThemeContext)去读取这个context的变量,无论这些子组件嵌套有多深

 const { globalStore } = useContext(GlobalContext);
function OtherComponents(){
  const theme = useContext(GlobalContext);
  return <button classname={theme}/>
}

只要来自父组件的context改变了, react就会重新渲染和更新ui

通常, 在不同文件的组件需要访问同一个context, 这就是为什么我们要在一个单独的文件里声明context, 然后将它export出去
// Contexts.js

import { createContext } from 'react';

export const GlobalContextProvider = GlobalContext.Provider;

export default GlobalContext;

如果想在子组件更新这些数据怎么办?

总不能从顶层传递一个setstate下来吧,这多麻烦啊, 特别是如果你的项目中组件嵌套很深的情况, 有个简单的方法,就是从context.Provider的value中 pass down 一个 dispatch 函数 from useReducer via context

const globalData = Object.assign({},  {
    mydata,
}

const [globalStore, dispatch] = useReducer(
  useCallback((preState, patchValue) => {
    return { ...preState, ...patchValue };
  }, []),
  globalData,
);

function App(){
 return (
   <GlobalContext.Provider
    value={{ globalStore, dispatch}} //改动在这里
    	<OtherComponents/>
    </GlobalContext.Provider>
 )
}

这样TodosApp中所有的子组件就可以使用dispatch去更新顶层数据了

function DeepChild(props) {
  // If we want to perform an action, we can get dispatch from context.  const dispatch = useContext(TodosDispatch);
  function handleClick() {
    dispatch({ type: 'add', text: 'hello' });
  }

  return (
    <button onClick={handleClick}>Add todo</button>
  );
}

参考自文档: https://legacy.reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down


网站公告

今日签到

点亮在社区的每一天
去签到