React Hook Form条件值控制:解决useEffect依赖警告并实现需求
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:
- Keep your form initialization logic intact (model value doesn't get wiped on load)
- Clear the model field whenever the manufacturer changes after initialization
- Eliminate React's missing dependency warning
内容的提问来源于stack exchange,提问作者Jake Jeon

