组件间的数据共享
在前端开发中,组件间的数据传递是一个重要的问题。日常工作中,我们大多会使用 props 进行数组传递。当组件结构较为简单时,这种方式非常直观。然而,当数据需要在深层次的嵌套组件中使用时,我们需要层层传递props,这种方式非常麻烦且容易出错。
在vue3中,可以通过Provide 可以在父组件中声明数据,然后在后代子组件Inject注入即可使用!在React中,我们可以使用useContext实现同样的效果。
什么是 useContext
React 的 useContext 是一个 Hook,用于共享全局状态或父组件的数据。它简化了通过 props 层层传递数据的过程,使得开发者可以在任意子组件中直接访问上下文中的数据。
使用场景
- 状态共享:如父组件信息、主题配置等(个人喜欢将父组件的数据派发给所有后代组件)。
 - 避免 
props drilling:减少不必要的中间层props传递。 
基本语法
我们通过共享用户信息为例演示其基本语法。
- 创建上下文对象
 
一般来说,context可以单独维护在一个文件内。
            
            
              js
              
              
            
          
          // context.tsx
import React, { createContext } from "react";
const MyContext = createContext(Context);
// 导出上下文对象,供父子组件消费
export default MyContext
        - 提供数据
 
使用 UserContext.Provider 将用户信息共享给子组件。
            
            
              js
              
              
            
          
          // 引入子组件
import Child from "./Child.tsx"
// 引入上下文对象
import MyContext from "./context.tsx"
// 父组件
const Parent = ({ children }) => {
  const [user, setUser] = useState({ name: "xiexiaoxie", age: 18 });
  const updateUser = (newUser) => setUser(newUser);
  return (
    <MyContext.Provider value={{ user, updateUser }}>
       <Child />
    </MyContext.Provider>
  );
};
export default Parent;
        使用MyContext.Provider包裹在应用的顶层,所有子组件都能访问 MyContext。value是提供给子组件的值。
- 子组件消费数据
 
通过 MyContext 使用上下文中的数据。
            
            
              js
              
              
            
          
          import React, { useContext } from "react";
// 引入上下文对象
import MyContext from "./context.tsx"
const Child = () => {
  // 导出并使用父组件的数据和方法
  const { user, updateUser } = useContext(MyContext);
  const handleChangeName = () => {
    updateUser({ ...user, name: "哈哈哈" });
  };
  return (
    <div>
      <p>用户名:{user.name}</p>
      <p>年龄:{user.age}</p>
      <button onClick={handleChangeName}>修改用户名</button>
    </div>
  );
};
export default Child;
        其他语法
createContext 的默认值
在使用 React.createContext 创建上下文时,可以通过参数为上下文设置一个 默认值(defaultValue) 。默认值的作用是 在没有使用对应的 Provider 包裹组件时,消费者组件会使用该默认值。
            
            
              js
              
              
            
          
          const MyContext = React.createContext({ user:"查无此人", updateUser:()=> {} });
        多个上下文的嵌套
如果需要同时使用多个上下文,可以将它们嵌套使用。
            
            
              js
              
              
            
          
          const ThemeContext = createContext();
const UserContext = createContext();
const App = () => (
  <ThemeContext.Provider value="dark">
    <UserContext.Provider value={{ name: "Alice" }}>
      <ChildComponent />
    </UserContext.Provider>
  </ThemeContext.Provider>
);
        为什么不使用Redux
熟悉Redux的同学一定会问,为什么不使用Redux,这是因为他们的适用的场景和功能范围存在显著差异。
- 功能范围
 
| 特性 | useContext | Redux | 
|---|---|---|
| 状态管理范围 | 适用于局部状态共享(如父子组件、主题、用户信息等) | 适用于全局状态管理 | 
| 复杂度 | 较简单,基于 React 内置 API | 较复杂,需要单独安装和配置 | 
| 状态来源 | 状态通常存储在某个组件的 useState中 | 
状态存储在单独的全局 Store | 
| 调试能力 | 无专用工具,调试依赖 React DevTools | Redux DevTools 提供强大的时间旅行调试 | 
| 中间件支持 | 不支持中间件 | 支持中间件(如 Redux Thunk、Saga) | 
- 适用场景
 
| 场景 | 推荐使用 useContext | 推荐使用 Redux | 
|---|---|---|
| 状态共享范围较小,逻辑简单 | ✅ | ❌ | 
| 状态复杂、需要统一管理 | ❌ | ✅ | 
| 需要支持时间旅行调试和状态跟踪 | ❌ | ✅ | 
| 状态变化频繁且依赖复杂 | ❌ | ✅ | 
| 轻量级项目,避免过度工具化 | ✅ | ❌ |