react函数组件中的深度监听如何实现?

发布于:2024-11-28 ⋅ 阅读:(14) ⋅ 点赞:(0)

    1.  如果你的对象结构比较简单,并且你只想对嵌套对象的某个字段进行监听,你可以直接监听该字段的变化,而不是监听整个对象。这样,你可以避免深度比较,简单直接地达到监听效果。

import React, { useState, useEffect } from 'react';

function DeepWatch() {
  const [state, setState] = useState({ count: 0, details: { name: 'John', age: 25 } });

  // 监听嵌套对象的具体字段变化
  useEffect(() => {
    console.log('Age changed:', state.details.age);
  }, [state.details.age]); // 只监听 age 字段的变化

  const updateState = () => {
    setState(prevState => ({
      ...prevState,
      details: { ...prevState.details, age: prevState.details.age + 1 }
    }));
  };

  return (
    <div>
      <p>Count: {state.count}</p>
      <p>Name: {state.details.name}</p>
      <p>Age: {state.details.age}</p>
      <button onClick={updateState}>Increment Age</button>
    </div>
  );
}
2.如果需要避免每次重新渲染都做深度比较,可以将前一个对象的引用保存在 useRef 中,然后对比当前值与之前的值,只有当值发生变化时才更新状态。

import React, { useState, useEffect, useRef } from 'react';
import isEqual from 'lodash.isequal';

function DeepWatch() {
  const [state, setState] = useState({ count: 0, details: { name: 'John', age: 25 } });
  const prevStateRef = useRef();

  useEffect(() => {
    if (!isEqual(state, prevStateRef.current)) {
      console.log('state has changed:', state);
      prevStateRef.current = state;
    }
  }, [state]); // 每次 state 变化时执行

  const updateState = () => {
    setState(prevState => ({
      ...prevState,
      details: { ...prevState.details, age: prevState.details.age + 1 }
    }));
  };

  return (
    <div>
      <p>Count: {state.count}</p>
      <p>Name: {state.details.name}</p>
      <p>Age: {state.details.age}</p>
      <button onClick={updateState}>Increment Age</button>
    </div>
  );
}

解释:

  • 使用 useRef 存储 state 的前一个值。
  • 使用 isEqual 比较当前的 state 和 prevStateRef.current,只有当它们不同才会执行副作用逻辑。
  • 通过 useRef 可以避免在每次 useEffect 触发时进行深度比较,从而提高性能。