初学 React Hooks 和 antd-design

文章详细探讨了ReactHooks中的useState和useRef在处理状态和数据流时的差异,强调useState的异步性和批量更新特性,以及useRef对于实时获取最新值的优势。同时,分析了antd设计的Modal组件在不同状态下如何进行props传递,并指出不可见Modal不会渲染子组件及影响props传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

umi: 3.5.40
React: 17.0.2
antd: 4.16.13

useState 和 useRef

使用小心得:

  1. setCount 之后不要直接使用 count ;
  2. 执行顺序要求比较严格的多用 useRef 会比较简洁。比如请求一个接口,获取响应值后马上带着响应值请求下一个接口,你可以用 let const useRef 去接这个响应值,但是千万别用 useState 去接,不然就要增加一个 useEffct ,否则你立马使用的肯定不是响应值。
  3. 能少用尽量少用,因为 useState 一旦改变状态会导致组件重新渲染。

const [count, setCount] = useState<number>(0); 参数一: state 声明的状态;参数二:更新参数一声明的状态的值。

  1. useState 会异步且批量更新数据,但是 useState 不能实时获取最新的值(React 更新状态数据之前多次执行 setCount ,取最后一次执行的 setCount);
  2. 基本数据类型的值发生改变或引用数据类型的引用地址发生改变时,再次使用 useState 的参数二才会再次执行;
  3. useState 的状态发生改变就会重新渲染组件;
  4. useEffect 通常和 useState 配合使用。(对于 useEffect 的副作用说法,我也不是很理解)
    • useEffect(() => {}); 陷入死循环
    • useEffect(() => {}, []); 挂载时执行一次
    • useEffect(() => {}, [count]); 挂载(也可能是赋默认值,我没分清)时,执行一次;此后,只要 count 基本数据类型是值,引用数据类型是引用地址发生改变时就会执行 useEffect 的回调函数,即参数一。(参数二放入 useRef , useRef 发生改变时不会执行 useEffect 的回调)
    • 当 useEffect 没有监听到依赖的数据发生改变时存在两种可能(我已知),一是引用地址没有发生改变,二是 useEffect 放在子组件上监听父组件传来的消息,而子组件在父组件中没有满足条件不渲染也会导致 useEffect 监听不到依赖数据的变化。

const countRef = useRef<number>(0);

  1. countRef 可以实时获取最新的值;
  2. countRef 的改变不会引起组件的重新渲染;
  3. countRef 的改变不会触发 useEffect 的回调函数。
import { Button } from "antd";
import { memo, useEffect, useRef, useState } from "react";

const TeachAssistantList: React.FC = () => {
  const countRef = useRef<number>(0);
  const countRef2 = useRef<number>(0);
  const [count, setCount] = useState<number>(0);
  const [count2, setCount2] = useState<number>(0);
  const [count3, setCount3] = useState<number>(0);

  // 单纯更改 countRef2.current 不会执行 useEffect 的回调函数,但是 setCount(count + 1); 后就会再次执行
  useEffect(() => {
    console.log(countRef2.current, 'countRef2');
    setCount2(count2 + 1);
  }, [countRef2.current]); // 改为 countRef2 会导致连 countRef2.current 都监听不到

  useEffect(() => {
    console.log(count);
  }, [count]);

  // setInterval(() => {
  //   console.log(count3, 'count3');
  //   setCount3(count3 + 1);
  // }, 10000);

  return <div>
    {console.log(123)}
    <Button onClick={() => countRef.current += 1}>改变 countRef</Button>
    <Button onClick={() => countRef2.current += 1}>改变 countRef2</Button>
    <Button onClick={() => {
      // setCount(1);
      // setCount(2);
      // setCount(3);

      // setCount(count);

      setCount(count + 1);
    }}>改变 count</Button>
  </div>
};

export default memo(TeachAssistantList);

antd-design 的 Modal 组件的 props 传值

结论

        不可见的 Modal 组件不会向子组件进行 props 传值且子组件也不会渲染,但是它不会影响 return 之外的函数执行,也不会影响 return 内非子组件的函数执行(标签和组件都没渲染)。
        两个 Modal 之间存在一个显示另一个隐藏时,这两个 modal 之间是并列关系而不是嵌套关系。

TeachAssistantList.tsx

import { Button } from "antd";
import { memo, useEffect, useState } from "react";
import FirstModal from "./FirstModal";

const TeachAssistantList: React.FC = () => {
  // 显示弹窗
  const [firstShowModal, setFirstShowModal] = useState<boolean>(false);
  const [count, setCount] = useState<number>(0);
  const [haha, setHaha] = useState<boolean>(false);

  useEffect(() => {
    console.log(count);
  }, [count]);
  
  useEffect(() => {
    console.log(haha);
  }, [haha]);
  
  return <div>
    {console.log(123)}
    <Button onClick={() => {
      setFirstShowModal(true);
    }}>显示弹窗</Button>
    <Button onClick={() => {
      setCount(count + 1);
      setHaha(!haha);
    }}>改变 count 和 haha 的值</Button>
    <FirstModal
      firstShowModal={firstShowModal}
      setFirstShowModal={setFirstShowModal}
      count={count}
      setCount={setCount}
      haha={haha}
      setHaha={setHaha}
    />
  </div>
};
export default memo(TeachAssistantList);

FirstModal.tsx

import { Button, Modal } from "antd";
import { memo, useEffect, useState } from "react";
import Watch from "../Watch";
import SecondModal from "../SecondModal";

interface PropsType {
  firstShowModal?: boolean;
  setFirstShowModal?: (firstShowModal: boolean) => void;
  count?: number;
  setCount?: (count: number) => void;
  haha?: boolean;
  setHaha?: (haha: boolean) => void;
}

const FirstModal: React.FC<PropsType> = ({
  firstShowModal = false,
  setFirstShowModal,
  count = 0,
  setCount,
  haha = false,
  setHaha
}) => {
  const [secondShowModal, setSecondShowModal] = useState<boolean>(false);

  useEffect(() => {
    console.log(count, 1);
  }, [count]);

  useEffect(() => {
    console.log(haha, 1);
  }, [haha]);

  return <Modal
    centered
    maskClosable={false}
    visible={firstShowModal}
    onCancel={() => setFirstShowModal?.(false)}
    onOk={() => setSecondShowModal(true)}
  >
    {console.log(456)}
    <Button onClick={() => {
      setCount?.(count + 1);
      setHaha?.(!haha);
    }}>改变 count 和 haha 的值</Button>
    <Watch
      type="FirstModal"
      count={count}
      haha={haha}
    />
    <SecondModal
      secondShowModal={secondShowModal}
      setSecondShowModal={setSecondShowModal}
      count={count}
      haha={haha}
    />
  </Modal>
}

export default memo(FirstModal);

{console.log(456)} 用 div 标签包裹,打印照样执行,如果没显示过 FirstModal 对话框并不会有 div 标签。
SecondModal.tsx

import { Button, Modal } from "antd";
import { memo, useEffect } from "react";
import Watch from "../Watch";

interface PropsType {
  secondShowModal?: boolean;
  setSecondShowModal?: (secondShowModal: boolean) => void;
  count?: number;
  haha?: boolean;
}

const SecondModal: React.FC<PropsType> = ({
  secondShowModal = false,
  setSecondShowModal,
  count = 0,
  haha = false
}) => {
  useEffect(() => {
    console.log(count, 2);
  }, [count]);

  useEffect(() => {
    console.log(haha, 2);
  }, [haha]);

  return <Modal
    centered
    visible={secondShowModal}
    onCancel={() => setSecondShowModal?.(false)}
    onOk={() => setSecondShowModal?.(false)}
  >
    {console.log(789)}
    <Watch
      type="SecondModal"
      count={count}
      haha={haha}
    />
  </Modal>
}

export default memo(SecondModal);

Watch.tsx

import { memo, useEffect } from "react";

interface PropsType {
  type?: string;
  count?: number;
  setCount?: (count: number) => void;
  haha?: boolean;
  setHaha?: (haha: boolean) => void;
}

const Watch: React.FC<PropsType> = ({
  type = 'normal',
  count = 0,
  haha = false
}) => {
  useEffect(() => {
    console.log(count, type);
  }, [count]);

  useEffect(() => {
    console.log(haha, type);
  }, [haha]);

  return <div>
    {console.log('watch', type)}
    <div>{ count }, { type }</div>
    <div>{ haha }, { type }</div>
  </div>
}

export default memo(Watch);

截图分析

图1:初始加载
antd-design 的 Modal 组件

“123” “0” “false” 都是 TeachAssistantList.tsx 打印的,“456” “0 1” “false 1” 都是 FirstModal.tsx 打印的。

  1. 子组件先挂载;
  2. SecondModal.tsx 和 Watch.tsx 都没有打印说明不可见的 Modal 不会渲染 Modal 内的子组件。

图2:点击一次“改变 count 和 haha 的值”
antd-design 的 Modal 组件

“123” “1” “true” 都是 TeachAssistantList.tsx 打印的,“456” “1 1” “true 1” 都是 FirstModal.tsx 打印的。

        说明 TeachAssistantList.tsx 的 count 和 haha 成功通过 props 传递给了 FirstModal.tsx 并且使 FirstModal.tsx 发生了重新渲染,此外, Modal 组件内的子组件没有挂载。


图3:点击一次“显示弹窗”(显示 FirstModal 对话框,不显示 SecondModal 对话框)
antd-design 的 Modal 组件

“123” 是 TeachAssistantList.tsx 打印的,“456” 是 FirstModal.tsx 打印的,“789” “1 2” “true 2” 都是 SecondModal.tsx 打印的,“watch FirstModal” “1 ‘FirstModal’” “true ‘FirstModal’” 都是 Watch.tsx 打印的。(此时的 count 为1, haha 为 true)

        因为没有打印 “watch SecondModal” “1 ‘SecondModal’” “true ‘SecondModal’”,所以不可见的 SecondModal 和不可见的 FirstModal 效果是一样的,说明 Modal 里面套 Modal 只需要考虑一个 Modal 的情况。


图5:点击 FirstModal 对话框的“确定”
antd-design 的 Modal 组件

“456” 是 FirstModal.tsx 打印的,"789"是 SecondModal.tsx 打印的,“watch SecondModal” “1 ‘SecondModal’” “true ‘SecondModal’” 都是 Watch.tsx 打印的。(此时的 count 为1, haha 为 true)


图6-1:点击两个 Modal 对话框的“取消”,回到最初的页面。
antd-design 的 Modal 组件
图6-2:点击两次“改变 count 和 haha 的值”
antd-design 的 Modal 组件
图6-3:先点击“显示弹窗”,弹出 FirstModal 对话框后点击 FirstModal 对话框的“确定”。
antd-design 的 Modal 组件
        上面三张图都没有打印过"true ‘SecondModal’" 和 “false ‘SecondModal’”,说明不可见的 Modal 组件不会向子组件进行 props 传值,可见的 Modal 组件需要传递的值发生改变时才会向子组件进行 props 传值。

<think>好的,我现在需要处理用户关于React与Ant Designantd)相关的前端技术介绍的查询。用户希望了解技术文档、入门教程以及功能特性。首先,我得回顾一下已有的引用内容,确保回答准确并符合用户提供的资料。 首先,引用[1]提到React-AntD基于React的组件化思想,每个组件都是独立且可复用的,这对大型项目管理UI很有帮助,同时支持TypeScript。引用[2]中的React-antd-Demo适用于初学者、快速原型开发团队协作,包含多种功能模块良好的文档。引用[3]指向ant-design-pro的官方文档,说明其作为脚手架的作用。引用[4]讨论了UI组件容器组件的区别,强调使用react-redux的connect函数。引用[5]则提供了Chrome插件开发的教程链接。 接下来,我需要组织这些信息,结构要清晰。可能需要分几个部分:功能特性、技术文档资源、入门教程推荐、应用场景以及常见问题。每个部分下都要引用合适的来源,确保正确标注引用标识。 在功能特性中,可以强调组件化、Ant Design的UI组件库、TypeScript支持、状态管理(如Redux)开发工具。技术文档资源需要列出官方文档、ant-design-pro社区资源。入门教程部分需要推荐官方教程、实践项目(如React-antd-Demo)进阶内容,比如Chrome插件开发。应用场景可以引用引用[2]提到的几个情况,比如初学者入门、快速原型等。 另外,用户示例中的相关问题部分需要生成相关问题,可能需要考虑Reactantd的结合优势、如何高效使用组件、与Redux的集成,以及实际项目案例。这些问题应基于引用内容,确保有据可依。 需要注意的是,所有行内数学表达式要用$...$,但根据用户的问题,可能这部分涉及较少,但如果有的话要正确处理。同时,确保LaTeX语法正确,不过当前主题可能不涉及数学公式,所以可能不需要。回答必须用中文,结构清晰,分点说明,并自然添加引用标识。 最后检查是否有遗漏的信息点,比如antd的功能特性是否覆盖全面,是否有推荐的教程资源未被提及,以及是否准确引用了提供的资料。确保没有添加未在引用中出现的内容,保持回答的真实可靠性。</think>### React与Ant Designantd)前端技术介绍 #### 一、功能特性 1. **组件化开发** React的核心思想是组件化,每个组件独立且可复用,特别适合大型项目管理[^1]。例如,Ant Design提供丰富的UI组件(如表格、表单、弹窗),可直接集成到React项目中。 2. **Ant Design UI库** Ant Designantd)是面向企业级的React UI组件库,具有以下特点: - **一致性设计**:统一的视觉风格与交互逻辑。 - **开箱即用**:提供数据展示、表单、导航等高频组件,例如: ```jsx import { Button, Table } from 'antd'; ``` - **高度可定制**:支持主题配置与样式覆盖[^2]。 3. **TypeScript支持** Ant DesignReact均对TypeScript提供原生支持,增强代码类型安全与开发效率。 4. **状态管理集成** 结合Redux或React Context API管理全局状态,容器组件通过`connect`函数与Redux通信,UI组件仅负责渲染[^4]。 5. **开发工具链** 支持Create React App、Webpack等工具快速搭建项目,并集成热更新、代码分割等优化功能。 --- #### 二、技术文档资源 1. **官方文档** - **React核心文档**:https://react.dev(涵盖Hooks、组件生命周期等)[^4] - **Ant Design文档**:https://ant.design(组件API与示例) - **Ant Design Pro**:企业级脚手架,提供权限管理、数据可视化等进阶方案[^3]。 2. **社区资源** - **React-antd-Demo**:包含登录、用户管理等模块的完整示例项目,适合快速原型开发[^2]。 - **Chrome插件开发教程**:结合React与Ant Design开发浏览器扩展[^5]。 --- #### 三、入门教程推荐 1. **基础学习路径** -React官方教程掌握JSX、组件通信与Hooks- 通过Ant Design文档实践常用组件(如`Form`、`Table`)。 2. **实战项目** - 参考`React-antd-Demo`搭建包含后端交互的全功能应用。 - 使用Ant Design Pro快速生成中后台管理系统[^3]。 3. **进阶内容** - 集成Redux进行状态管理(参考容器组件设计模式)。 - 开发Chrome插件(Manifest V3规范与Antd结合)。 --- #### 四、典型应用场景 1. **企业级后台系统** 如数据管理平台、CMS系统,依赖Ant Design的高质量表格与表单组件[^3]。 2. **快速原型开发** 利用预制组件库在几小时内完成可交互Demo。 3. **团队协作项目** 标准化组件与项目结构降低协作成本,例如统一表单校验规则。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值