You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Hook Form条件值控制:解决useEffect依赖警告并实现需求

Fixing the React Hook Dependency Warning While Preserving Form Initialization Logic

Got it, let's break down what's going on here first: when you add initialized to the second useEffect's dependency array, the hook fires right after initialized switches to true (post-form initialization). This triggers setValue("model", ""), which wipes out the model value you just set with reset(oneItem). Without initialized in the dependencies, the logic works but React throws that annoying missing dependency warning.

Here are a couple of clean ways to fix this without sacrificing functionality or ignoring the warning (never ignore warnings unless you're 100% sure why!):

Solution 1: Use a Ref to Track Initialization State

Refs don't trigger re-renders or useEffect runs when their current value changes, making them perfect for tracking this kind of one-time initialization state. This avoids the dependency issue entirely because we don't need to include the ref in the useEffect dependency array (and React won't warn about it).

const MyForm = ({ itemId }) => {
  const { watch, setValue, handleSubmit, reset, register } = useForm()
  // Replace useState with useRef
  const initializedRef = useRef(false)
  const manufacturerWatchValue = watch("manufacturer")

  useEffect(() => {
    // Initializing Form Here
    itemId && (async () => {
      const oneItem = await getOneResult(itemId)
      reset(oneItem)
      initializedRef.current = true // Update ref instead of state
    })()
    // Terminating Form Here
    return () => {
      reset({})
      initializedRef.current = false // Reset ref on cleanup
    }
  }, [reset, itemId])

  useEffect(() => {
    // Check the ref's current value instead of state
    if (initializedRef.current) {
      setValue("model", "")
    }
  }, [manufacturerWatchValue, setValue]) // No need to add initializedRef here

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

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input type="text" name="model" ref={register} />
      <input type="text" name="manufacturer" ref={register} />
    </form>
  )
}

Solution 2: Add a Guard Clause to Skip Initialization Trigger

If you prefer to keep using useState for initialized, you can add an extra check to make sure we only clear the model when the manufacturer value changes after initialization. We can track the initial manufacturer value with a ref to compare against:

const MyForm = ({ itemId }) => {
  const { watch, setValue, handleSubmit, reset, register } = useForm()
  const [initialized, setInitialized] = useState(false)
  const manufacturerWatchValue = watch("manufacturer")
  const initialManufacturerRef = useRef(null)

  useEffect(() => {
    // Initializing Form Here
    itemId && (async () => {
      const oneItem = await getOneResult(itemId)
      reset(oneItem)
      initialManufacturerRef.current = oneItem.manufacturer // Store initial value
      setInitialized(true)
    })()
    // Terminating Form Here
    return () => {
      reset({})
      setInitialized(false)
      initialManufacturerRef.current = null
    }
  }, [reset, itemId])

  useEffect(() => {
    // Only clear model if initialized AND manufacturer has changed from initial value
    if (initialized && manufacturerWatchValue !== initialManufacturerRef.current) {
      setValue("model", "")
    }
  }, [manufacturerWatchValue, setValue, initialized]) // Now we can safely include initialized

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

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input type="text" name="model" ref={register} />
      <input type="text" name="manufacturer" ref={register} />
    </form>
  )
}

Solution 3: Use React Hook Form's watch Callback (Alternative Approach)

React Hook Form's watch accepts a callback function that runs when the watched field changes. This lets us avoid useEffect entirely for this logic, which can simplify things:

const MyForm = ({ itemId }) => {
  const { watch, setValue, handleSubmit, reset, register } = useForm()
  const [initialized, setInitialized] = useState(false)

  useEffect(() => {
    // Initializing Form Here
    itemId && (async () => {
      const oneItem = await getOneResult(itemId)
      reset(oneItem)
      setInitialized(true)
    })()
    // Terminating Form Here
    return () => {
      reset({})
      setInitialized(false)
    }
  }, [reset, itemId])

  // Use watch with a callback instead of useEffect
  watch("manufacturer", (newValue, oldValue) => {
    // Only run after initialization
    if (initialized) {
      setValue("model", "")
    }
  })

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

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input type="text" name="model" ref={register} />
      <input type="text" name="manufacturer" ref={register} />
    </form>
  )
}

All three of these solutions will:

  1. Keep your form initialization logic intact (model value doesn't get wiped on load)
  2. Clear the model field whenever the manufacturer changes after initialization
  3. Eliminate React's missing dependency warning

内容的提问来源于stack exchange,提问作者Jake Jeon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 19:47:45