React中的useContext

文章类型:React

发布者:hp

发布时间:2025-10-16

一:定义

允许你在组件中订阅React的Context(上下文)而不需要使用传统的Context.Consumer组件

二:是什么

简单来说,就是解决props信息传递给子组件层层传递的问题,允许Context父组件向其下层无论多深的任何组件提供信息

第一步创建=>(createContext(defaultValue))

第二步使用=>(<MyContext.Provider value={someValue}>)

第三步消费=>(useContext(MyContext) )

三:代码

//引入Context
import { createContext,useContext } from 'react'


// 1. 创建 Context(默认值为 '3')
 const NameContext = React.createContext('3');


// 2. 父组件:提供 Context 值
function Parent() {
  return (
    <NameContext.Provider value="1"> {/* 这里提供值 "1" */}
      <Child />
    </NameContext.Provider>
  );
}

// 3. 中间组件
function Child() {
  return <Son />;
}

// 4. 孙组件:消费 Context
function Son() {
  const name = useContext(NameContext); // 获取值
  
  return <div>名字: {name}</div>; // 输出 "名字: 1"
}

四:注意点

1:忘记使用Provider=>必须确保树中有对应的Provider

2:Provider得value没有变化但是组件重新渲染=>只要父组件有变化,那么即使value没变化,也会重新渲染

3:多层Provider嵌套时值获取=>会返回离它最近的Provider值

4:在类组件使用情况=>useContext只能在函数组件使用,类组件使用需要Context.Consumer或static contextType

五:优化

1:拆分Context,不要把所有状态放在一个Context中,避免所有消费组件重新渲染

// 好的做法 - 拆分Context
<UserContext.Provider value={user}>
  <UserDispatchContext.Provider value={setUser}>
    <ProfileContext.Provider value={profile}>
      {/* ... */}
    </ProfileContext.Provider>
  </UserDispatchContext.Provider>
</UserContext.Provider>

2:使用userMeno记忆化value,避免重新渲染

const user = useMemo(() => ({ name: 'John', age: 30 }), []);
return (
  <UserContext.Provider value={user}>
    {/* ... */}
  </UserContext.Provider>
);

3:使用React.memo将消费组件记忆化,避免子组件不必要渲染

const ThemedButton = React.memo(function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme === 'dark' ? '#333' : '#EEE' }}>按钮</button>;
});

六:使用场景

1:主题切换

2:用户认证

七:总结

1:React Context提供了一种在组件树中共享数据的方式,而不必显式地通过组件树的每一层传递props。

2:它主要解决了"prop drilling"(属性钻取)问题,即当需要在多层嵌套组件中传递数据时,中间层组件即使不需要这些数据,也必须接收并向下传递这些props

八:拓展

(1)useContext和Redux有什么区别?

Context:

内置于React,无需额外依赖

适合共享简单的、不频繁变化的数据

没有中间件、时间旅行调试等高级功能

当Provider的值变化时,所有消费组件都会重新渲染

Redux:

需要单独安装

适合管理复杂的应用状态

提供中间件支持、时间旅行调试等功能

使用选择器精确控制组件的重新渲染

(2)何时应该使用Context而不是Redux?

Context:

共享主题、用户认证等简单的全局状态

数据更新不频繁

应用规模较小

Redux:

应用状态复杂且更新频繁

需要中间件处理异步逻辑

(3)在类组件如何使用Context?

使用Context.Consumer

class ThemedButton extends React.Component {
  render() {
    return (
      <ThemeContext.Consumer>
        {theme => (
          <button style={{ background: theme }}>按钮</button>
        )}
      </ThemeContext.Consumer>
    );
  }
}

使用static contextType

class ThemedButton extends React.Component {
  static contextType = ThemeContext;
  
  render() {
    const theme = this.context;
    return <button style={{ background: theme }}>按钮</button>;
  }
}

(4)创建自定义Hook封装Context?

function useTheme() {
  const context = useContext(ThemeContext);
  if (context === undefined) {
    throw new Error('useTheme必须在ThemeProvider内使用');
  }
  return context;
}

// 使用
function ThemedButton() {
  const { theme, toggleTheme } = useTheme();
  // ...
}


评论
0条评论遵守法律,文明用语,共同建设文明评论区

暂无评论,快来发表第一条评论吧~