ReactHooks

1. 关于子组件提交数据的写法

你写的 onSubmit={props.onSubmit} 这种思路是对的,但在 Ant Design 的实际代码中,会稍微有一点点区别。

通常 Modal 组件本身没有 onSubmit 属性,它用的是 onOk。而且,子组件在提交时,通常需要先把自己的表单数据拿出来,再传给父组件。

常见的做法是:

复制代码
<UpdateForm
  // 1. 父传子:把控制弹窗显示的变量传过去
  updateModalOpen={updateModalOpen} 
  // 2. 父传子:把当前要编辑的那一行数据传过去
  values={currentRow || {}} 
  // 3. 子传父(回调):子组件点"提交"时,调用父组件定义的 handleUpdate 函数
  onSubmit={async (value) => {
    const success = await handleUpdate(value);
    if (success) {
      handleUpdateModalOpen(false); // 关闭弹窗
      actionRef.current?.reload();  // 刷新表格
    }
  }}
  // 4. 子传父(回调):子组件点"取消"时,让父组件关闭弹窗
  onCancel={() => handleUpdateModalOpen(false)}
/>






const UpdateForm = (props) => {
  const [form] = Form.useForm(); // 创建表单实例

  const handleOk = async () => {
    // 1. 校验表单并获取值
    const values = await form.validateFields();
    // 2. 调用父组件传过来的 onSubmit 逻辑
    props.onSubmit(values);
  };

  return (
    <Modal open={props.updateModalOpen} onOk={handleOk} onCancel={props.onCancel}>
       <Form form={form} initialValues={props.values}>
          {/* 表单项... */}
       </Form>
    </Modal>
  );
};

2. 多层级通讯(爷爷传给孙子)

你提到的 Vue 里的 provide/inject,在 React 中对应的官方方案是 Context API

方案 A:Context API(最常用)

这就像是在组件树上方架设了一个"广播站"。

  1. 创建上下文const MyContext = createContext();
  2. 提供数据(爷爷辈) :使用 <MyContext.Provider value={...}> 包裹子组件。
  3. 消费数据(孙子辈) :使用 useContext(MyContext) 钩子直接获取,不需要经过中间的爸爸组件。

方案 B:全局状态管理

如果你的项目非常大,或者很多页面都要共享这些数据(比如用户信息、主题颜色),通常会用:

  • Redux / Zustand:把数据存在页面之外的一个"大仓库"里,谁要谁去取。
  • UmiJS 插件 :既然你代码里有 @umijs/max,它内置了一个非常简单的全局状态管理------useModel
    • src/models 下写个文件。
    • 任何组件只需要 const { initialState } = useModel('@@initialState'); 就能拿到数据。

3. 正常开发中常用的 Hooks 函数

在 React 的日常搬砖中,90% 的场景都在用下面这几个:

|-----------------|-------------------------------------------------|----------|
| Hook | 作用 | 直观比喻 |
| useState | 定义变量,改变它会触发页面刷新。 | 变量寄存器 |
| useEffect | 处理"副作用"。比如:页面刚加载时去调 API,或者某个变量变了我要跟着做点啥。 | 监听器/生命周期 |
| useRef | 1. 引用 DOM 元素或组件(如actionRef );2. 存一个不会触发刷新的变量。 | 记事本/钩子 |
| useMemo | 计算复杂数据并缓存,防止重复计算。 | 缓存器 |
| useCallback | 缓存函数,防止父组件刷新导致子组件跟着乱刷(性能优化)。 | 函数保险箱 |
| useContext | 跨级取数据(如上文所说)。 | 无线接收机 |

总结

  • 父子通讯:靠 Props,子传父靠回调。
  • 跨级通讯 :Vue 用 inject,React 用 useContextuseModel
  • 常用 Hooks :最最核心的是 useState(存数据)和 useEffect(发请求/监听)。

具体代码:

复制代码
import { createContext } from 'react';
// 创建一个广播站,会创建不同的 Context 对象
export const DeptContext = createContext();
export const ThemeContext = createContext();
export const UserContext = createContext();
// 以上是MyContext 的文件


//爷爷组件(提供数据)
import { DeptContext } from './MyContext';
const UserPage = () => {
  const [deptName, setDeptName] = useState('开发部');

  return (
    // 使用 Provider 包裹,value 里的东西,后代都能直接拿
    <DeptContext.Provider value={deptName}>
      <ParentComponent /> {/* 爸爸组件,它不需要接收 deptName 这个 prop */}
    </DeptContext.Provider>
  );
};


//孙子元素,直接接受:
//孙子组件拿数据时,必须明确说"我要听 DeptContext 频道":const deptName = useContext(DeptContext);它绝不会拿到 UserContext 里的数据
//因为你在 useContext 括号里传入的 Context 对象 是唯一的钥匙。
import { useContext } from 'react';
import { DeptContext } from './MyContext';

const GrandSon = () => {
  // 孙子直接从广播站拿数据,不需要爸爸传话
  const deptName = useContext(DeptContext);
  
  return <div>当前部门是:{deptName}</div>;
};

useEffect 如何监听变化

在 React 里,没有专门的 watch****函数 ,所有的监听活儿都由 useEffect 承包了。

它是怎么监听的?

useEffect 接收两个参数:

  1. 回调函数:要做的事情。
  2. 依赖数组:你想监听谁,就把谁放进去。
  3. useEffect****vs Vue 的 watch

虽然它们都能监听数据,但有几个核心区别:

|-----------|-------------------------------|-------------------------------------------|
| 特性 | Vue 的 watch | React 的 useEffect |
| 触发时机 | 默认只在值改变时触发。 | 初始化渲染完成后一定会执行一次,然后才是值改变时触发。 |
| 新旧值对比 | 自动提供 (newValue, oldValue) 。 | 不提供旧值 。如果你非要旧值,得自己用 useRef 存一份手动对比。 |
| 写法 | 指定监听某个变量名。 | 将变量放入数组,支持同时监听多个(数组里任何一个变了都会触发)。 |
| 自动运行 | immediate: true 才在初次运行。 | 默认就是 immediate (总是先运行一遍)。 |

复制代码
useEffect(() => {
  console.log('部门 ID 变了,我要执行一些逻辑');
  
  // 这里可以写你想做的操作,比如弹个窗
  if (selectDeptId) {
     fetchUserByDept(selectDeptId);
  
  }

}, [selectDeptId]); // <--- 关键!这就是"监听器"。只要 selectDeptId 变了,上面的代码就会跑。

useEffect****可以写多个吗?

答案是:可以,而且非常推荐写多个!

在 React 开发中,我们提倡 "关注点分离" 。与其把所有逻辑都挤在一个巨大的 useEffect 里,不如按功能拆开:

关于监听 :多用 useEffect****没问题,但要记住, 别在 useEffect****里修改它自己监听的那个值 ,否则会陷入"无限死循环"(它变了 \(\rightarrow \) 触发监听 \(\rightarrow \) 你改了它 \(\rightarrow \) 它又变了 \(\rightarrow \) 又触发监听)

复制代码
// 监听 1:专门负责根据部门 ID 加载数据
useEffect(() => {
  if (deptId) {
    loadTableData(deptId);
  }
}, [deptId]);

// 监听 2:专门负责监听用户输入,实时验证名字格式
useEffect(() => {
  if (userName.length > 10) {
    message.warning('名字太长啦!');
  }
}, [userName]);

// 监听 3:只在页面刚打开时执行一次(依赖数组为空)
useEffect(() => {
  console.log('欢迎来到用户管理页面');
}, []);
相关推荐
蝎子莱莱爱打怪1 小时前
用好CC,事半功倍!Claude Code 命令大全,黄金命令推荐、多模型配置、实践指南、Hooks 和踩坑记录大全
前端·人工智能·后端
本末倒置1832 小时前
VS Code 这次稳了!CSS Anchor Positioning 彻底终结 WebView 定位卡顿
前端
MonkeyKing71552 小时前
Flutter状态管理实战:全局、局部、页面状态拆分指南
前端·flutter
Panzer_Jack2 小时前
Copiwaifu:一个和 Claude Code、Codex、Copilot 等 AI 编程工具联动的 Live2D 桌宠[特殊字符]
前端·人工智能·copilot·web·live2d·pixi.js·easy-live2d
开源情报局3 小时前
从小红书评论区挖需求:我准备用 opencode 写一个 Chrome 插件
前端·javascript·chrome
用户125758524363 小时前
XYGo Admin 三级权限体系:RBAC 动态路由 + v-auth 按钮控制 + 字段级过滤全解析
前端
小李子呢02113 小时前
前端八股JS---Map / Set / WeakMap / WeakSet
开发语言·前端·javascript
冴羽3 小时前
3 招让你的 Shadcn 出海应用性能提升 40 倍
前端·javascript·next.js