当前位置: 首页 > wzjs >正文

广州海珠网站制bittorrentkitty磁力猫

广州海珠网站制,bittorrentkitty磁力猫,广东东莞市最新疫情,郑州航空港区建设局网站目录 一、React生命周期图例1. 挂载/创建阶段(组件首次渲染)4步2. 更新阶段(props/state变更)5步3. 卸载阶段(组件从DOM移除)4. 错误处理(React 16新增) 二、Hooks 对生命周期的替代…

目录

  • 一、React生命周期图例
    • 1. 挂载/创建阶段(组件首次渲染)4步
    • 2. 更新阶段(props/state变更)5步
    • 3. 卸载阶段(组件从DOM移除)
    • 4. 错误处理(React 16+新增)
  • 二、Hooks 对生命周期的替代
    • 1. 状态管理(替代 this.state)
    • 2. 副作用管理(替代生命周期钩子)
    • 3. 性能优化(替代 shouldComponentUpdate)
    • 4. 其他常用数据保存 Hooks
  • 三、hooks其他问题
    • 1. useEffect 与 useLayoutEffect 的区别?
    • 2. 如何避免 useEffect 无限循环?
    • 3. constructor 和 getDerivedStateFromProps 的区别
    • 4. useState和useReducer
    • 5. 多个 useEffect 的执行顺序
    • 6. 如何避免 useEffect 无限循环
    • 7. useMemo和 React.memo
    • 8. 自定义React hooks
    • 9. setState和useState是同步还是异步?区别是什么?

一、React生命周期图例

在这里插入图片描述

函数何时调用其他典型场景hooks等效实现
constructor仅在组件实例化时执行一次唯一可以直接修改state,很少使用初始化内部状态相当于useState/useReducer 初始化状态
getDerivedStateFromProps外部传入属性发生变化,例如:setState(),forceUpdate()state需要从props初始化时使用,每次render都会调用。维护两者状态一致会增加复杂度,尽量不要使用表单控件获取默认值useMemo、useCallback 、useEffect+useState
shouldComponentUpdate属性变化时,除了forceUpdate()决定Virtual DOM是否要重绘性能优化React.memo,用于浅比较 props 来决定是否重新渲染组件
render渲染UI描述UI,必须写的方法函数组件本身就是渲染逻辑
getSnapshotBeforeUpdate页面render之前调用,state已更新获取render之前DOM状态使用 useLayoutEffect 在 DOM 更新前读取值,并通过 useRef 存储快照
componentDIdMountUI渲染完成后调用只执行一次发起ajax等外部请求useEffect(…, [])
componentDitUpdate每次UI更新时调用页面需要根据props变化重新获取数据useEffect(…, [dependency])
componentWillUnmount组件被移除时调用资源释放useEffect 返回的清理函数return

1. 挂载/创建阶段(组件首次渲染)4步

  • 执行顺序:constructor → getDerivedStateFromProps → render → componentDidMount

2. 更新阶段(props/state变更)5步

  • 触发条件:props 变化、state 变化、forceUpdate()
  • 执行顺序:getDerivedStateFromProps → shouldComponentUpdate → render →
    getSnapshotBeforeUpdatecomponentDidUpdate

3. 卸载阶段(组件从DOM移除)

  • componentWillUnmount:用于清理副作用(如定时器、订阅)

4. 错误处理(React 16+新增)

  • componentDidCatch

二、Hooks 对生命周期的替代

1. 状态管理(替代 this.state)

  • useState:基础状态管理。
const [count, setCount] = useState(0);
  • useReducer:复杂状态逻辑(类似 Redux 的 reducer)
const [state, dispatch] = useReducer(reducer, initialState);

2. 副作用管理(替代生命周期钩子)

  • useEffect:相当于 componentDidMount + componentDidUpdate + componentWillUnmount 的组合
// 依赖项为空数组:仅挂载时执行(类似 componentDidMount)
useEffect(() => {// 初始化逻辑return () => {// 组件卸载时执行:清理逻辑(类似 componentWillUnmount)};
}, []);// 无依赖项:每次渲染后执行(类似 componentDidMount + componentDidUpdate)
useEffect(() => {// 副作用逻辑
});// 特定依赖变化时执行
useEffect(() => {// 仅当 count 变化时执行(初始也执行一次?)
}, [count]);

3. 性能优化(替代 shouldComponentUpdate)

  • React.memo:浅比较 props,阻止重复渲染(函数组件版 PureComponent)。
const MyComponent = React.memo((props) => { ... });
  • useMemo:缓存计算结果,避免重复计算。
const expensiveValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • useCallback:缓存函数引用,避免子组件不必要的更新。
const handleClick = useCallback(() => {doSomething(a);
}, [a]);

4. 其他常用数据保存 Hooks

  • useRef:保存可变值(类似类组件的实例属性);获取 DOM 节点(替代 createRef)。
  • useContext:跨层级传递数据(替代 Context.Consumer)。

三、hooks其他问题

1. useEffect 与 useLayoutEffect 的区别?

对比useEffectuseLayoutEffect
执行时机异步执行,在浏览器渲染后触发(不阻塞页面绘制)。同步执行,在 DOM 更新后、浏览器绘制前触发(可能阻塞渲染)。
适用场景数据获取、订阅等不影响渲染的操作需要读取 DOM 布局并立即更新的场景(如测量元素尺寸、滚动位置恢复)。

2. 如何避免 useEffect 无限循环?

  • 检查依赖项:确保依赖项数组中不包含引用类型(如对象、函数),或使用 useCallback/useMemo 缓存。
  • 过滤不必要的更新:在 useEffect 内部通过条件判断过滤重复操作。
  • 使用 useRef 存储可变值:避免依赖项变化触发无限循环。

3. constructor 和 getDerivedStateFromProps 的区别

方法constructorgetDerivedStateFromProps
调用时机组件实例化时调用(初始化阶段)每次渲染前调用(初始化 + 更新阶段)
是否可以更新 state可以(通过 this.state = { … })必须返回新 state 或 null(纯函数)
是否可以访问 this可以(需先调用 super(props))不可以(静态方法,无 this)
典型用途初始化 state、绑定事件处理函数根据 props 动态更新 state(如受控组件)

注意:不能在constructor里调用 setState(此时组件尚未挂载)。用this.state = { … }赋值

4. useState和useReducer

特性useStateuseReducer
状态结构基础类型(number、string、boolean)或对象复杂对象或数组
更新逻辑直接修改(setState(newValue))通过 reducer 函数处理(纯函数)
适用场景状态逻辑简单,状态更新相互独立(如计数器、表单值)复杂状态逻辑,更新逻辑分散,需要撤销 / 重做、时间旅行调试(如多值联动、状态历史记录)
组件间共享需逐层传递 state 和 setState可结合 Context 全局共享 dispatch
调试与测试较简单更易预测(纯函数),便于测试和时间旅行调试
多次调用多次调用 setState 可能触发多次渲染(React 18 中自动批处理已优化)。单个 dispatch 触发一次更新,更适合复杂状态变更。

useReducer使用

const initialState = {loading: false,data: null,error: null
};const reducer = (state, action) => {switch (action.type) {case 'FETCH_START':return { ...state, loading: true }; // 仅更新 loadingcase 'FETCH_SUCCESS':return { ...state, loading: false, data: action.payload }; // 更新 loading 和 datacase 'FETCH_ERROR':return { ...state, loading: false, error: action.error }; // 更新 loading 和 errordefault:return state;}
};const DataFetcher = () => {const [state, dispatch] = useReducer(reducer, initialState);return (<div><button onClick={() => dispatch({ type: 'FETCH_START', payload: { id: 1 } })}>start</button>{/* 其他操作... */}</div>);
};

5. 多个 useEffect 的执行顺序

useEffect(() => {console.log(1)return () => {console.log(2)};
}, []);useEffect(() => {console.log(3);return () => {console.log(4)}
});useEffect(() => {console.log(5)return () => {console.log(6)}
}, [count]);

以上代码挂载时、卸载时、count变化时的执行顺序是什么?

  • 挂载时(首次渲染)
    输出:1 → 3 → 5

    • 第一个 useEffect(依赖项为空数组 []):仅在挂载时执行。
    • 第二个useEffect(无依赖项):在每次渲染后执行,包括首次渲染。
    • 第三个 useEffect(依赖项为 count):在首次渲染时,由于count 存在初始值(假设为 0),也会执行。
  • 卸载时
    输出 6 → 4 → 2

    • 第三个 useEffect的return(依赖 count):最先注册,最后清理(6)
    • 第二个 useEffect的return(无依赖):其次注册,其次清理(4)。
    • 第一个 useEffect的return(空依赖):最后注册,最先清理(2)。
  • count 变化时
    输出:6 → 5 → 4 → 3

    • 第三个 useEffect:
      • 清理上一次的副作用(6)。
      • 执行新的副作用(5)。
    • 第二个 useEffect:
      • 清理上一次的副作用(4)。
      • 执行新的副作用(3)。

useEffect 的清理函数(return 返回的函数)遵循 “后进先出”(LIFO) 的栈结构规则,useEffect顺序执行,遇到return后压入栈中,所以第一个useEffect的return先入栈,第三个useEffect的return最后入栈;卸载时,第三个useEffect的return先出栈执行

6. 如何避免 useEffect 无限循环

  • 无限循环的常见原因
    当 useEffect 的依赖项包含引用类型(如对象、函数)时,如果每次渲染都生成新的引用,会导致 useEffect 不断触发
  • 解决
    • ① useCallback 缓存函数引用,仅在依赖项变化时才重新创建函数

      const [count, setCount] = useState(0);// 仅当依赖项 [] 变化时才重新创建函数(这里永远不变)
      const fetchData = useCallback(() => {console.log('Fetching data...');
      }, []); // ✅ 只创建一次函数useEffect(() => {fetchData();
      }, [fetchData]); // ✅ 仅触发一次
      
    • ② useMemo 缓存计算结果,避免重复计算复杂值

      const [count, setCount] = useState(0);// 仅当 count 变化时才重新计算 expensiveValue
      const expensiveValue = useMemo(() => {return performExpensiveCalculation(count);
      }, [count]);useEffect(() => {console.log(expensiveValue);
      }, [expensiveValue]); // ✅ 仅在 count 变化时触发
      
    • ③ useRef 存储可变值,修改 ref 不会导致组件重新渲染

      const [count, setCount] = useState(0);
      const prevCountRef = useRef(0);useEffect(() => {prevCountRef.current = count; // 保存当前值
      }, [count]);const prevCount = prevCountRef.current; // 获取上一次的值
      

7. useMemo和 React.memo

关于 useMemo 和 React.memo 的区别,这是 React 性能优化中的常见问题。虽然名字相似,但它们的功能和应用场景完全不同

特性useMemoReact.memo
类型Hook(函数组件内部使用)高阶组件(包裹函数组件)
作用对象值(计算结果、函数等)组件本身
触发条件依赖项变化时重新计算props 浅比较不相等时重新渲染
应用场景避免重复计算复杂值、缓存函数引用避免组件因相同 props 重复渲染
默认行为不自动执行,需手动包裹 自动执行 props 浅比较
  • React.memo 的浅比较限制
    • 仅浅比较 props:如果 props 包含引用类型(如对象、数组),需确保引用不变。
    • 函数 props:需配合 useCallback 或 useMemo 使用,避免父组件每次渲染时创建新函数。

8. 自定义React hooks

  • 定义:自定义 Hooks 是一个函数,其名称以 use 开头,内部可以调用其他 Hooks。
  • 核心价值:复用有状态的逻辑(如订阅、动画、表单验证),同时不污染组件结构。
  • 与组件的区别:组件返回 UI,而自定义 Hooks 返回数据或副作用。

自定义 Hook 示例:

import { useState, useEffect } from 'react';
// 使用 localStorage 持久化状态
function useLocalStorage(key, initialValue) {// 1. 内部使用 useState 管理状态const [value, setValue] = useState(() => {try {const storedValue = localStorage.getItem(key);return storedValue ? JSON.parse(storedValue) : initialValue;} catch (error) {return initialValue;}});// 2. 使用 useEffect 添加副作用useEffect(() => {localStorage.setItem(key, JSON.stringify(value));}, [key, value]); // 3. 指定依赖项,控制副作用触发时机// 4. 返回状态和修改状态的函数(类似 useState),也可以返回对象或函数return [value, setValue];
}

9. setState和useState是同步还是异步?区别是什么?

特性class 组件的 setState函数组件的 useState
执行时机批量异步(多数情况下)批量异步(多数情况下)
强制同步场景1. 原生事件回调 2. setTimeout/setInterval1. 原生事件回调 2. setTimeout/setInterval
状态更新方式合并对象(this.state 是累积的)完全替换(需手动合并 setState(prev => ({…prev, key})))
多次调用行为合并为一次更新(对象浅合并)按顺序执行(函数式更新)
  • 异步机制:React 为了优化性能,会批量处理多个状态更新,因此在同一个事件循环中多次调用 setState 或 useState 可能不会立即生效。

    // Class 组件
    handleClick() {this.setState({ count: this.state.count + 1 });console.log(this.state.count); // 输出旧值(异步更新)
    }// 函数组件
    const handleClick = () => {setCount(count + 1);console.log(count); // 输出旧值(异步更新)
    };
    
  • 同步场景

    • 原生事件回调

      // Class 组件
      componentDidMount() {document.getElementById('btn').addEventListener('click', () => {this.setState({ count: this.state.count + 1 });console.log(this.state.count); // 输出新值(同步更新)});
      }// 函数组件
      useEffect(() => {document.getElementById('btn').addEventListener('click', () => {setCount(count + 1);console.log(count); // 输出新值(同步更新)});
      }, []);
      
    • setTimeout/setInterval 回调

      场景Class 组件的 setState函数组件的 useState
      状态更新时机立即更新(同步)不立即更新(异步)
      闭包捕获问题无(通过 this.state 获取最新值)有(闭包捕获初始值)可通过 useRef 存储可变值,使用最新状态
      多次调用合并合并为一次更新(对象浅合并)按顺序执行(函数式更新)
      渲染触发次数一次(批量处理)一次(React 18 自动批处理)

      Class 组件的setState在setTimeout中:

      class Counter extends React.Component {state = { count: 0 };handleClick = () => {setTimeout(() => {this.setState({ count: this.state.count + 1 });console.log(this.state.count); // 输出 1(状态立即更新)this.setState({ count: this.state.count + 1 });console.log(this.state.count); // 输出 2(状态立即更新)}, 1000);};render() {console.log('Rendering...'); // 仅触发一次渲染return <button onClick={this.handleClick}>{this.state.count}</button>;}
      }
      

      函数组件的useState在setTimeout中:

      const Counter = () => {const [count, setCount] = useState(0);const handleClick = () => {setTimeout(() => {setCount(prev => prev + 1); // 使用函数式更新,获取最新状态console.log(count); // 输出 0(状态未立即更新,但更新逻辑正确)setCount(prev => prev + 1); // 基于最新状态更新,最终 count 变为 2console.log(count); // 输出 0}, 1000);};return <button onClick={handleClick}>{count}</button>;
      };
      
  • 批量更新机制的差异

    • setState:多次调用会合并对象,仅触发一次渲染。
    • useState:多次调用函数式更新会按顺序执行,触发多次渲染(React 18 中自动批处理优化为一次)。
      // Class 组件
      handleClick() {this.setState({ count: this.state.count + 1 });this.setState({ count: this.state.count + 1 }); // 合并为一次更新,最终 count 只加 1
      }
      // 函数组件(React 18 之前)
      const handleClick = () => {setCount(prev => prev + 1); // 第一次更新setCount(prev => prev + 1); // 第二次更新,最终 count 加 2
      };
      
  • 获取更新后的状态

    • Class 组件:setState使用回调函数

    • 函数组件:useState使用useEffect

      this.setState({ count: this.state.count + 1 },() => {console.log(this.state.count); // 输出新值}
      );
      const [count, setCount] = useState(0);useEffect(() => {console.log(count); // 每次 count 变化时执行
      }, [count]);const handleClick = () => {setCount(count + 1);
      };
      
http://www.dtcms.com/wzjs/144624.html

相关文章:

  • 建设公寓租房信息网站搜索引擎营销怎么做
  • 广东网站建设服务商百度指数是干嘛的
  • 品牌网站建设哪个好网站排名首页前三位
  • 网站计划电商运营怎么做如何从零开始
  • 网站制作策划方案汕头seo按天付费
  • b2b网站有哪些方面seo技术交流
  • 九江专业网站建设定制电脑软件推广平台
  • 淘宝做推广网站百度销售
  • 山西省三基建设办公室网站宁德市蕉城区
  • 一级a做爰免费网站seo代做
  • 主题商店网站设计怎样做竞价推广
  • 免费网站怎么建seo网站推广服务
  • 怎样做企业的网站友情链接查询工具
  • 建设银行杭州纪念币预约网站日照高端网站建设
  • 营销型网站具备的二大能力社群营销成功案例
  • 北京效果图公司众志seo
  • 东莞做网站优化搜索风云榜
  • app开发公司不退款该怎么投诉seo深圳网络推广
  • phpcms 视频网站模板营销推广渠道
  • 七星彩网站开发英文外链seo兼职
  • 大连网站 设计公司佛山网站建设正规公司
  • 免费企业建站系统源码广州品牌营销策划公司排名
  • 2022适合小学生的简短新闻优化网站排名方法
  • 国外专门做杂志的共享网站seo基础知识包括什么
  • 河南英文网站建设公司广告门
  • html个人主页长沙seo网站优化
  • 个人公司网站建设答辩seo诊断专家
  • 做足球推荐网站能赚钱吗长春关键词搜索排名
  • 网站的竞价怎么做狼雨的seo教程
  • 北京大型网站建设台州seo网站排名优化