跳到主要内容

useDidUpdate

组件更新时执行回调的 Hook,跳过首次挂载,相当于 class 组件的 componentDidUpdate

基本用法

实时编辑器
function Demo() {
  const [count, setCount] = useState(0);
  const [updateCount, setUpdateCount] = useState(0);

  useDidUpdate(() => {
    setUpdateCount((c) => c + 1);
  }, [count]);

  return (
    <div>
      <div
        style={{
          padding: '20px',
          backgroundColor: 'var(--ifm-color-emphasis-100)',
          borderRadius: '8px',
          marginBottom: '12px',
        }}
      >
        <div>计数: {count}</div>
        <div style={{ color: 'var(--ifm-color-primary)' }}>
          更新次数: {updateCount}
        </div>
      </div>
      <Button onClick={() => setCount(count + 1)}>增加</Button>
    </div>
  );
}
结果
Loading...

监听特定值

只在特定依赖变化时执行:

实时编辑器
function Demo() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [log, setLog] = useState([]);

  useDidUpdate(() => {
    setLog((logs) => [...logs, `名字更新为: ${name}`]);
  }, [name]);

  return (
    <div>
      <div style={{ marginBottom: '12px' }}>
        <Input
          placeholder="输入名字"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
      </div>
      <div style={{ marginBottom: '12px' }}>
        <Input
          placeholder="输入邮箱(不会触发日志)"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
      </div>
      {log.length > 0 && (
        <div
          style={{
            padding: '12px',
            backgroundColor: 'var(--ifm-color-emphasis-100)',
            borderRadius: '6px',
            fontSize: '14px',
          }}
        >
          <strong>更新日志:</strong>
          {log.map((item, index) => (
            <div key={index}>{item}</div>
          ))}
        </div>
      )}
    </div>
  );
}
结果
Loading...

同步到 localStorage

值变化时同步到本地存储:

实时编辑器
function Demo() {
  const [text, setText] = useState('');
  const [saved, setSaved] = useState(false);

  useDidUpdate(() => {
    localStorage.setItem('draft-text', text);
    setSaved(true);
    const timer = setTimeout(() => setSaved(false), 2000);
    return () => clearTimeout(timer);
  }, [text]);

  return (
    <div>
      <Textarea
        placeholder="输入文本(自动保存)"
        value={text}
        onChange={(e) => setText(e.target.value)}
        rows={4}
      />
      {saved && (
        <div
          style={{
            marginTop: '12px',
            padding: '8px 12px',
            backgroundColor: 'var(--ifm-color-success-lightest)',
            borderRadius: '4px',
            fontSize: '14px',
          }}
        >
          ✓ 已保存
        </div>
      )}
    </div>
  );
}
结果
Loading...

表单验证

字段变化时执行验证:

实时编辑器
function Demo() {
  const [password, setPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');
  const [error, setError] = useState('');

  useDidUpdate(() => {
    if (password && confirmPassword) {
      if (password !== confirmPassword) {
        setError('两次密码不一致');
      } else {
        setError('');
      }
    }
  }, [password, confirmPassword]);

  return (
    <div>
      <div style={{ marginBottom: '12px' }}>
        <Input
          type="password"
          placeholder="输入密码"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
        />
      </div>
      <div style={{ marginBottom: '12px' }}>
        <Input
          type="password"
          placeholder="确认密码"
          value={confirmPassword}
          onChange={(e) => setConfirmPassword(e.target.value)}
        />
      </div>
      {error && (
        <div
          style={{
            padding: '8px 12px',
            backgroundColor: 'var(--ifm-color-danger-lightest)',
            color: 'var(--ifm-color-danger-dark)',
            borderRadius: '4px',
            fontSize: '14px',
          }}
        >
          {error}
        </div>
      )}
    </div>
  );
}
结果
Loading...

API

参数

function useDidUpdate(
fn: () => void,
dependencies?: any[]
): void
参数说明类型默认值
fn更新时执行的回调函数() => void-
dependencies依赖数组any[]undefined

返回值

无返回值。

与 useEffect 的区别

特性useDidUpdateuseEffect
首次挂载❌ 不执行✅ 执行
更新时✅ 执行✅ 执行
使用场景只关心更新挂载和更新都关心

注意事项

  • 组件首次挂载时不会执行回调
  • 只在依赖项变化时执行
  • 如果不传依赖数组,每次更新都会执行
  • 避免在回调中修改依赖值,可能造成无限循环

使用场景

  • 数据同步: 状态变化时同步到外部系统
  • 表单验证: 字段变化时执行验证
  • 日志记录: 记录值的变化
  • 副作用: 响应特定状态变化
  • API 调用: 搜索词变化时重新请求数据