zustand获取 useStore 的值为空,解决办法如下

57 阅读2分钟
react-hook-form 结合 zustand 的写法时, 在组件 useEffect 内部调用 useStore的方法,在组件内 获取 useStore 的值,但是值为空, 怎么解决? 代码应该怎么修改更加具有性能优化

当在 react-hook-form 结合 zustand 时,如果在 useEffect 内部调用 useStore 的方法并发现值为空,这通常是因为 useEffect 的执行时机问题,或者是 zustand 状态在 useEffect 调用时尚未准备好。为了优化性能,可以采取以下几种方法:

优化方案

1. 使用 zustandsubscribe 监听状态变化

通过 zustandsubscribe 机制监听状态的变化,并在状态更新时设置 react-hook-form 的值。这种方法确保在 zustand 的状态准备好时,及时更新表单值。

import React, { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useStore } from './store'; // 从 zustand 获取 store

function MyForm() {
  const { register, handleSubmit, setValue } = useForm();
  const formData = useStore((state) => state.formData); // 获取状态
  const subscribe = useStore((state) => state.subscribe);

  useEffect(() => {
    if (formData) {
      setValue('firstName', formData.firstName);
      setValue('lastName', formData.lastName);
    }
    // 订阅状态变化
    const unsubscribe = subscribe((newState) => {
      if (newState.formData) {
        setValue('firstName', newState.formData.firstName);
        setValue('lastName', newState.formData.lastName);
      }
    });

    return () => unsubscribe(); // 清理订阅
  }, [formData, setValue, subscribe]);

  const onSubmit = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('firstName')} placeholder="First Name" />
      <input {...register('lastName')} placeholder="Last Name" />
      <button type="submit">Submit</button>
    </form>
  );
}

export default MyForm;

2. 使用 defaultValues 初始化表单

在表单初始化时通过 useFormdefaultValues 直接设置表单默认值。如果 zustand 的状态在组件渲染时就已经准备好,这种方法最为简洁和高效。

import React from 'react';
import { useForm } from 'react-hook-form';
import { useStore } from './store';

function MyForm() {
  const formData = useStore((state) => state.formData);

  const { register, handleSubmit } = useForm({
    defaultValues: formData, // 使用 Zustand 的状态初始化表单
  });

  const onSubmit = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('firstName')} placeholder="First Name" />
      <input {...register('lastName')} placeholder="Last Name" />
      <button type="submit">Submit</button>
    </form>
  );
}

export default MyForm;

3. 避免不必要的重新渲染

zustand 状态变化时,确保只更新必要的组件,以避免不必要的重新渲染。通过将 zustand 的选择器函数细化,只订阅与组件相关的状态部分。

import React from 'react';
import { useForm } from 'react-hook-form';
import { useStore } from './store';

function MyForm() {
  const formData = useStore((state) => state.formData);

  const { register, handleSubmit } = useForm({
    defaultValues: formData, // 直接使用状态初始化表单
  });

  const onSubmit = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('firstName')} placeholder="First Name" />
      <input {...register('lastName')} placeholder="Last Name" />
      <button type="submit">Submit</button>
    </form>
  );
}

export default MyForm;

总结

为了解决在 useEffect 中调用 useStore 时状态为空的问题,建议使用 zustandsubscribe 方法来监听状态变化,或者直接使用 defaultValues 初始化表单,确保状态在渲染前已准备好。通过优化状态订阅和减少不必要的重新渲染,可以进一步提升性能。