티스토리 뷰

전에 포스팅을 보면 알겠지만 react 경험을 앞으로 정리 할 것 같다.

 

검색조건 select box를 만드는데 validation을 편하게 하기 위해서 react-select에 react-form-hook의 controller를 입혔다.


  const useFormReturn = useForm({
    mode: 'onChange'
  })
...
  const makeSubmitHandler = ({ useFormReturn }: { useFormReturn: UseFormReturn }) => {
    return useFormReturn.handleSubmit(async fieldValues => {
      console.log(fieldValues)
    })
  }
...
  const submitHandler = makeSubmitHandler({ useFormReturn })


<Controller
          name="company"
          control={useFormReturn.control}
          render={({ field: { onChange, value } }) => (
            <Select
              options={companyList.map(c => ({
                label: c.name,
                value: c.code
              }))}
              onChange={option => onChange(option.value)}
            />
          )}
        />
<StyledErrorSpan>
   <>{errors.company?.message}</>
</StyledErrorSpan>

이렇게 해서 잘 되길래 좋아했는데 초기화가 안되는 현상을 발견했다.

useFormReturn.reset() 을 호출하면 다른 컴포넌트들은 초기화 되는데 select box가 그대로이다.

 

원인은 몇가지가 섞인건데

1. onChange()에 option이 아니라 option.value를 넣어서 option들 중에서 못찾아서 그런거

2. <Select에 value={value}를 설정해서 controller의 value와 select의 value를 동기화 시켜야하는것 같고

3. reset할때 초기값을 넣어주는게 맞는것 같았다.

 

수정한 소스는 아래와 같다.

const initSearchInfo= {
   company: null, 
}

const useFormReturn = useForm({
    mode: 'onChange'
  })

  const makeSubmitHandler = ({ useFormReturn }: { useFormReturn: UseFormReturn }) => {
    return useFormReturn.handleSubmit(async fieldValues => {
      console.log(fieldValues)
    })
  }

  const submitHandler = makeSubmitHandler({ useFormReturn })

  useEffect(() => {
    useFormReturn.reset(initSearchInfo)
  }, [])


        <form onSubmit={submitHandler}>
<Controller
          name="company"
          control={useFormReturn.control}
          render={({ field: { onChange, value } }) => (
            <Select
              value={value}
              options={companyList.map(c => ({
                label: c.name,
                value: c.code
              }))}
              onChange={option => onChange(option)}
            />
          )}
        />
        <StyledErrorSpan>
          <>{errors.company?.message}</>
        </StyledErrorSpan>
</form>
useFormReturn.reset(initSearchInfo)

 

근데 그랬더니 submit으로 온 값 fieldValues에 company값이 옵션 객체로 온다...

이건 그래서 변환하는 로직을 넣었는데, 더 좋은 방법이 없나 고민중.

datepicker 컴포넌트도 타입이 Date라 변환했다. 

const makeSubmitHandler = ({ useFormReturn }: { useFormReturn: UseFormReturn }) => {
    return useFormReturn.handleSubmit(async fieldValues => {
      Object.entries(fieldValues).forEach(([key, item]) => {
        if (item && typeof item === 'object' && item?.value !== null) {
          if (item instanceof Date) {
            fieldValues[key] = getFormatDate(item)
          } else {
            fieldValues[key] = item.value
          }
        }
      })

      console.log(fieldValues)
    })
  }

 

프로젝트 소스를 여기에 수정해서 올린거라 오타가 있을 수도 있습니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함