Skip to content

useWatch

입력의 변경을 구독하기 위한 React 훅

</> useWatch: ({ control?: Control, name?: string, defaultValue?: unknown, disabled?: boolean }) => object

watch API와 유사하게 동작하지만, 이 훅은 리렌더링을 커스텀 훅 레벨에서 격리하여 애플리케이션의 성능을 향상시킬 수 있습니다.

Props


NameTypeDescription
namestring | string[] | undefined필드의 이름.
controlObjectuseForm이 제공하는 control 객체. FormProvider를 사용하는 경우, 이 props는 선택 사항입니다.
defaultValueunknown초기 렌더링 전에 useWatch가 반환할 기본 값.

참고: defaultValue가 제공되면 첫 번째 렌더링 시에는 항상 defaultValue을 반환합니다.
disabledboolean = false구독을 비활성화하는 옵션.
exactboolean = false이 prop은 입력 필드의 이름 구독에 대한 정확한 일치가 가능하도록 합니다.

Return


ExampleReturn
useWatch({ name: 'inputName' })unknown
useWatch({ name: ['inputName1'] })unknown[]
useWatch(){[key:string]: unknown}
RULES
  • useWatch의 초기 반환 값은 항상 defaultValue 또는 useFormdefaultValues에 있는 값을 반환합니다.

  • useWatchwatch의 유일한 차이점은 루트(useForm) 레벨 또는 커스텀 훅 레벨에서의 업데이트에 있습니다.

  • useWatch의 실행 순서는 중요합니다. 즉, 구독이 설정되기 전에 폼 값을 업데이트 하면, 해당 변경 사항이 무시됩니다.

    setValue("test", "data")
    useWatch({ name: "test" }) // ❌ 값이 업데이트 된 후 구독이 발생하고, 변경 사항이 반영되지 않음
    useWatch({ name: "example" }) // ✅ 입력 값 변경이 반영되고, 리렌더링이 트리거됨
    setValue("example", "data")

    위 문제는 다음과 같은 간단한 커스텀 훅을 사용하여 해결할 수 있습니다:

    const useFormValues = () => {
    const { getValues } = useFormContext()
    return {
    ...useWatch(), // 폼 값 업데이트를 구독합니다.
    ...getValues(), // 항상 최신 폼 값과 병합합니다.
    }
    }
  • useWatch의 결과는 useEffect의 의존성 배열 대신 렌더 단계(render phase)에 최적화되어 있습니다. 값의 변화를 감지하려면 값 비교를 위한 외부 커스텀 훅을 사용하는 것이 좋습니다.

Examples:


import React from "react"
import { useForm, useWatch } from "react-hook-form"
interface FormInputs {
firstName: string
lastName: string
}
function FirstNameWatched({ control }: { control: Control<FormInputs> }) {
const firstName = useWatch({
control,
name: "firstName", // 이름을 지정하지 않으면 전체 폼을 감지하며,['firstName', 'lastName']을 사용하면 둘 다 감지할 수 있습니다.
defaultValue: "default", // 렌더링 전 기본값
})
return <p>Watch: {firstName}</p> // firstName이 변경될 때만 커스텀 훅 레벨에서 리렌더링
}
function App() {
const { register, control, handleSubmit } = useForm<FormInputs>()
const onSubmit = (data: FormInputs) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>First Name:</label>
<input {...register("firstName")} />
<input {...register("lastName")} />
<input type="submit" />
<FirstNameWatched control={control} />
</form>
)
}
import React from "react"
import { useForm, useWatch } from "react-hook-form"
function Child({ control }) {
const firstName = useWatch({
control,
name: "firstName",
})
return <p>Watch: {firstName}</p>
}
function App() {
const { register, control } = useForm({
defaultValues: {
firstName: "test",
},
})
return (
<form>
<input {...register("firstName")} />
<Child control={control} />
</form>
)
}

고급 필드 배열

import React from "react"
import { useWatch } from "react-hook-form"
function totalCal(results) {
let totalValue = 0
for (const key in results) {
for (const value in results[key]) {
if (typeof results[key][value] === "string") {
const output = parseInt(results[key][value], 10)
totalValue = totalValue + (Number.isNaN(output) ? 0 : output)
} else {
totalValue = totalValue + totalCal(results[key][value], totalValue)
}
}
}
return totalValue
}
export const Calc = ({ control, setValue }) => {
const results = useWatch({ control, name: "test" })
const output = totalCal(results)
// 필드 배열로 결과를 계산하기 위해 독립적인 리렌더링
console.log(results)
setValue("total", output)
return <p>{output}</p>
}

지원해 주셔서 감사합니다

프로젝트에서 React Hook Form이 유용하다고 생각하신다면, 스타를 눌러 지원해 주시길 부탁드립니다.