react中的useContext--为什么使用(一)

React 的数据传递流程

在 React 中,数据传递 通常是自上而下 的,也就是父组件把数据通过 props 传递给子组件 ,子组件无法直接修改父组件的数据。

例子:父组件向子组件传递数据
jsx 复制代码
const Parent = () => {
  const user = { name: "John", age: 24 };
  
  return <Child user={user} />;
};

const Child = ({ user }) => {
  return (
    <div>
      <h2>姓名: {user.name}</h2>
      <h2>年龄: {user.age}</h2>
    </div>
  );
};

问题不大,看起来很简单,对吧?


子组件传递数据的"噩梦"

但如果子组件需要修改父组件的数据 ,就必须通过回调函数,让子组件把新的数据"反向"传回父组件,让父组件更新数据。

例子:子组件修改父组件数据
jsx 复制代码
const Parent = () => {
  const [user, setUser] = useState({ name: "John", age: 24 });

  // 让子组件调用这个方法来修改 user
  const updateUser = (newName) => {
    setUser({ ...user, name: newName });
  };

  return <Child user={user} updateUser={updateUser} />;
};

const Child = ({ user, updateUser }) => {
  return (
    <div>
      <h2>姓名: {user.name}</h2>
      <button onClick={() => updateUser("Alice")}>改名为 Alice</button>
    </div>
  );
};

这样,点击按钮后,John 就会变成 Alice,但这还不算太糟糕。

真正的问题是:如果有很多层嵌套怎么办?


多层嵌套时的"数据传递地狱"

如果 Child 不是直接在 Parent 里面,而是嵌套了好几层 ,每一层都要手动传 props,就会变得非常痛苦。

数据传递"地狱"示例
jsx 复制代码
const Parent = () => {
  const [user, setUser] = useState({ name: "John", age: 24 });

  const updateUser = (newName) => {
    setUser({ ...user, name: newName });
  };

  return <Level1 user={user} updateUser={updateUser} />;
};

// 一层又一层地传递 props...
const Level1 = ({ user, updateUser }) => <Level2 user={user} updateUser={updateUser} />;
const Level2 = ({ user, updateUser }) => <Level3 user={user} updateUser={updateUser} />;
const Level3 = ({ user, updateUser }) => <Level4 user={user} updateUser={updateUser} />;
const Level4 = ({ user, updateUser }) => (
  <div>
    <h2>姓名: {user.name}</h2>
    <button onClick={() => updateUser("Alice")}>改名为 Alice</button>
  </div>
);

问题:

  • 你要在 每一层组件 都写 props 传递,代码变得冗长且难以维护。
  • 组件越多,数据传递越混乱,很容易出错。
  • 这个问题被称为 "Props Drilling"(属性挖掘),就像挖矿一样,数据要一层一层往下挖。

如何解决?------ useContext 来救场!

React 提供了 useContext ,它就像一个全局数据仓库 ,可以让任何组件直接访问 数据,而不需要层层 props 传递。

步骤 1:创建 Context
jsx 复制代码
import { createContext, useState } from "react";

// 1. 创建 Context
const UserContext = createContext();

// 2. 创建 Provider 组件
const UserProvider = ({ children }) => {
  const [user, setUser] = useState({ name: "John", age: 24 });

  const updateUser = (newName) => {
    setUser({ ...user, name: newName });
  };

  return (
    <UserContext.Provider value={{ user, updateUser }}>
      {children}  {/* 这里的 children 让所有子组件都能访问这个 Context */}
    </UserContext.Provider>
  );
};

export { UserContext, UserProvider };

步骤 2:子组件直接用 useContext 读取数据
jsx 复制代码
import { useContext } from "react";
import { UserContext } from "./UserContext";

const UserProfile = () => {
  const { user, updateUser } = useContext(UserContext);

  return (
    <div>
      <h2>姓名: {user.name}</h2>
      <button onClick={() => updateUser("Alice")}>改名为 Alice</button>
    </div>
  );
};

export default UserProfile;

步骤 3:在 App.js 里包裹 Provider
jsx 复制代码
import React from "react";
import { UserProvider } from "./UserContext";
import UserProfile from "./UserProfile";

const App = () => {
  return (
    <UserProvider>
      <UserProfile />
    </UserProvider>
  );
};

export default App;

为什么 useContext 很强大?

  1. 避免了"数据传递地狱" :不需要层层 props 传递,所有组件都能直接访问数据。
  2. 代码更清晰:不管组件嵌套多少层,都能方便地读取和更新数据。
  3. 性能更好 :不会因为 props 变化导致所有中间组件都重新渲染。

总结

  1. 传统数据传递方式(props)

    • 适合小型项目,数据传递简单时使用。
    • 但是当层级变深时,props drilling 让代码变得难以维护。
  2. useContext 方式

    • 适合共享状态的场景,比如用户信息、主题设置、语言切换等。
    • 让所有组件都能直接访问数据 ,避免 props 层层传递。
  3. 最佳实践

    • 如果数据只在父子组件之间传递 ,用 props 即可。
    • 如果数据需要被多个组件共享,使用 useContext 来简化代码。

🚀 现在,你可以摆脱"数据传递地狱",用 useContext 让 React 代码更清爽!

相关推荐
结局无敌1 小时前
React Native for OpenHarmony 实战:三方库 react-native-modal-dialog 的鸿蒙化适配指南
深度学习·算法·react native·react.js·harmonyos
拖孩1 小时前
AI 帮我写的小程序「厨菜记」上线满月了,挣了两百块!!!
前端·后端·微信小程序
用户360055579001 小时前
Kestrel_VLLM - 13 · 为什么排除 MoE FFN Tiling 与 Tensor Core
前端
Hilaku2 小时前
AI 流式输出都用 SSE,什么时候必须换 WebSocket?
前端·javascript·程序员
奇牙coding2 小时前
Codex CLI 升级后多文件编辑静默失效:config.yaml 枚举变更排查与修复指南
java·前端·javascript·ai
小羊没烦恼!2 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
程序员老赵2 小时前
Docker 部署 Filestash:轻松搭建浏览器文件管理平台
前端·docker·开源
夏天要喝冰可乐2 小时前
给 23 万字修仙小说造个阅读站:浏览器内打包 EPUB 分页阅读 + 三主题实战
前端·产品·全栈
茶底世界之下2 小时前
林间步道要不要加暗角?用 Awaking 把强度收在20%
前端·ios·图片资源
执子念的飞鱼2 小时前
纯前端预览 275 种文件格式是怎么做到的
前端·vue.js·react.js