๐ช [React] react-hook-form์ ๋ํ ์์ ๊ณ ์ฐฐ
FilterDropdown์ ๋ง๋ค๋ ์ค์ ์๊ฐ ๋ณํ์ ํ๋ฆ
๊ฐ์
์ฐธ๊ณ ) FilterDropdown
์ปดํฌ๋ํธ๋ input ๋ ๊ฐ์ checkbox ํ๋๋ฅผ ๊ฐ์ง ๋๋กญ๋ค์ด ์ปดํฌ๋ํธ์ด๋ค.
- ์ฒ์์๋ ๊ทธ๋ฅ ๋ค ๋๋ ค๋ฐ์์ ๋ง๋ค์๋ค๊ฐ
- ์ง๋์จ input์ ์ปดํฌ๋ํธ๋ก ๋นผ์ (invalid ํผ๋๋ฐฑ ๋ฑ์ ํจ๊ป ๊ด๋ฆฌํ๋ ค๊ณ )
- ์ด๋ฌ๋๊น ๊ฐ์ด๋ ์๋ฌ๋ฅผ ๋ค props๋ก ๋ฐ์์์ผํ๋ค
- ์ ๋นํ ๋ฆฌํฉํ ๋ง
- ๊ธฐํ ๋๋ฉด input ๊ด๋ จ valid ์ฒดํฌํ๋๊ฑฐ๋ ๋ค ์ปค์คํ ํ ์ผ๋ก ์ ๊ณตํด์ผ์ง
- ์ด? ๊ทธ๊ฒ ๋ฐ๋ก react-hook-form..?
ํด์ ๋ฆฌํฉํ ๋ง์ ์งํํ๊ฒ ๋ ๊ฒ์ด์๋ค.
๋ณธ๋ก
๊ทธ๋์,
์ด์ฌํ react-hook-form์ผ๋ก ๊ฐ์์น์ ๋ค.
Custom Validation with dependency
์๋์ฒ๋ผ ์ง๋์จ ๊ตฌ๊ฐ ๊ด๋ จํ ์ ํจ์ฑ ๊ฒ์ฌ ๋ก์ง์ด ํ์ํ๋ค. validate๋ผ๋ ํญ๋ชฉ ์ถ๊ฐ๋ก ๊ฐ๋ฅํ๋๋ฐ, ์๋ฌ ๋ฉ์ธ์ง ๋๊ฒจ์ฃผ๋ ๋ถ๋ถ์์๋ ์ด์ง ์ ๋ฅผ ๋จน์์๋ค. (๊ณต์ ๋ฌธ์๋ฅผ ์ ์ฐพ์๋ณด๋ฉด ์น์ ํ๊ฒ ๋์์๋๋ฐ ์ ์์ฐพ์๋ณธ ์์ ์ตํ..)
// ๋ณดํต์ ์ด๋ ๊ฒ,
{
max: {
value: 100,
message: '100๋ณด๋ค ์์ ์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.'
}
}
// ๊ทผ๋ฐ ์ปค์คํ
ํ๊ฒ ์ฃผ๋ ๊ฒฝ์ฐ๋ ์ด๋ ๊ฒ..!
{
validate: (v) => (v < max) || '์๋ฌ ๋ฉ์ธ์ง...'
}
input์ด ๋ณ๊ฒฝ ๋ ๋๋ง๋ค ์ฌ๊ฒ์ฌ๊ฐ ํ์ํ๊ฑธ?
๊ทธ๋, ์ด๊ฑด ํด๊ฒฐํ๋๋ฐโฆ
์ง๋์จ ๊ตฌ๊ฐ ๊ด๋ จ ์ ํจ์ฑ ๊ฒ์ฌ๋ ์์ ๊ตฌ๊ฐ(min)์๋ง ์ถ๊ฐํ๋, ๋ ๊ตฌ๊ฐ(max)์ด ๋ณ๊ฒฝ๋๋ฉด ๊ฒ์ฌ๋ฅผ ๋ค์ ํด์ฃผ์ด์ผ ํ๋ค. ([20, 10]
์์ [20, 100]
์ผ๋ก ๋ณ๊ฒฝํ๋ฉด invalid๋ฅผ ๋นผ์ฃผ์ด์ผํ๋๊น)
๊ทธ๋์ ์๊ฐํ ๋ฐฉ๋ฒ์ validate๋ฅผ ์ถ๊ฐํ์ง ์๊ณ setErrors๋ฅผ ํตํด min, max ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค error๋ฅผ set, reset ํด์ฃผ๊ธฐ์๋ค.
useEffect(() => {
if (inputKey === MIN) {
if (minValue > maxValue) {
setError(MIN, {
type: 'range',
message: '์ง๋์จ ์์ ๊ตฌ๊ฐ์ ๋ ๊ตฌ๊ฐ๋ณด๋ค ํฌ์ง ์๊ฒ ์ค์ ํด ์ฃผ์ธ์.',
});
} else if (minValue < 100) {
clearErrors(MIN);
}
}
}, [minValue, maxValue]);
์ ์ง๊ธ ์๊ฐ์ ์ ์ ํจ์ฑ ๋ฌธ๊ตฌ๋ฅผ min, max ๋ ๋ค์๊ฒ ์ฃผ๊ณ ์ ํจ์ฑ ๊ฒ์ฌํ ๋๋ v๊ฐ ์๋๋ผ min, max๋ก ํ์ผ๋ฉด..?
๊ทธ๋ฐ๋ฐโฆ
validate ์ฒดํฌ๊ฐ input์ด ๋ณํ ๋ ๋ง๋ค ์ํ ํ๋๊ฒ ์๋๊ฐ๋ณด๋ค..?
์๋์ฒ๋ผ validate callback ๋ด๋ถ์ console์ โinnerโ๋ก ์ฐ์ด๋ณด์๋๋ฐ ๋งค๋ฒ ์ฐํ์ง๊ฐ ์์.
validate๊ฐ ํธ๋ฆฌ๊ฑฐ ๋๋ ์์ (max: 100์ด๋ฉด input์ด 100์ด ๋๋ ๊ทธ ์์ )์๋ง ๋ถ๋ฆฌ๊ณ , ํ์ธํ๋ ๋ฐฉ์์ธ ๊ฒ ๊ฐ์(๊ทธ ์ธ์๋ ์ ์ง - ์๋ฌ ๋ฉ์ธ์ง๊ฐ ๊ณ์ ๋ณด์ด๊ฑฐ๋, ์ฌ๋ผ์ง ์ฑ๋ก)
๋ฐ๋ผ์ ๋๋ ์ปค์คํ ํ ์ ํจ์ฑ ๊ฒ์ฌ๋ก, watch๋ก ๋ณ๊ฒฝ๋๊ณ ์๋ min ์ด max ๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์์ง ํ์ธํ๋๋ก ํ์ผ๋๊น, ์ฒ์์ผ๋ก min > max ๊ฐ ๋๋ ๊ทธ ์์ ์ ํ ๋ฒ ๋ถ๋ ค์ ์๋ฌ๊ฐ ์ฐํ๊ณ , ๊ทธ ์ดํ์๋ ์๋ฌ ๋ฉ์ธ์ง๊ฐ ์ฌ๋ผ์ง๋ ๋ฏ?
๋ง์ ๊ต์ฅํ ์ ์ ์๊ฒ ์จ๋์๋๋ฐ, ํ ๋ง๋๋ก ์ง๊ธ ๋ด๊ฐ ์ง๋ ์ฝ๋์์๋ input ๊ฐ์ด ๋งค๋ฒ ๋ฐ๋ ๋๋ง๋ค ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ํํ์ง ์๋๋ค๊ฐ ํฌ์ธํธ. ๋ฐ๋ผ์ ๋ด๊ฐ ์ํ๋ ๋์์ ๋ง๋ค์ด๋ด๊ธฐ ์ํด์๋ ์ด์ฉ ์ ์์ด useEffect ๋ฑ์ผ๋ก ๋ณ๊ฒฝ๋ ๋๋ง๋ค ๊ฒ์ฌ๋ฅผ ๋ฐ๋ก ์ํํด์ฃผ์ด์ผ ํ๋ค.
reValidateMode: 'onChangeโ
๋ผ๋ ๊ฑธ ์ฐพ์๋๋ฐ, ์ด๊ฒ๋ ์์ ํ ๋ด๊ฐ ์๊ฐํ๋๋ก ๋์ํ์ง๋ ์๋๋ค.. ใ
(์ฝ๋ ์กฐ๊ฐ์ ์๋์)
{...register(inputKey, {
max: {
value: 100,
message: '100 ์ดํ์ ์ซ์๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์.',
},
validate: {
range: () => {
console.log('inner', minValue, maxValue);
return (
minValue <= maxValue ||
'์ง๋์จ ์์ ๊ตฌ๊ฐ์ ๋ ๊ตฌ๊ฐ๋ณด๋ค ํฌ์ง ์๊ฒ ์ค์ ํด ์ฃผ์ธ์.'
);
},
},
setValueAs: (v) => (v !== '' ? Number.parseInt(v, 10) : ''),
})
}
์ดํด ์๋๋ ๊ฑฐ ํ๋ ๋ ๋ฐ๊ฒฌํ๋ค.
์ isValid ๋ true ์ธ๋ฐ errors๋ ๋จ์์์ง? (isValid ๊ฐ ๋ง๋ ์ํฉ์ด๋ค.)
๋์์ ์ฒจ๋ถ๋ฅผ ๋ชปํ๋๋ฐ, ์ํฉ์ ์ ๋ฆฌํ์๋ฉด errors๊ฐ ํ ๋ฐ์ ๋๋ฆฌ๊ฒ ๋ ๋๋ง ๋๊ณ ์์๋ค. (๋ค๋ฅธ ์์์ ์ํด ๋ ๋๋ง์ด ํ ๋ฒ ๋ ์ผ์ด๋๋ฉด ๋ง๋ ๊ฐ..)
triger
์๋ฌด๋๋ trigger๋ฅผ ์ฌ์ฉํด์ผํ ๊ฒ ๊ฐ์ง?
์์กด์ฑ์ด ์๋ ์ ํจ์ฑ ๊ฒ์ฌ๋ ๋ด๊ฐ ์์์ ์๋ํ๋ ์ฝ๋๋ค๋ก๋ ์ ๋๋ก ๋์ ์ํ๋๊ฒ ๋ง์๋ค. (์ข ๊ณ ์ณ์ฃผ์ง.. ์ ์ด๋ ๊ฒ ๋ฐ๋ก trigger๋ฅผ ๋นผ๋จ์๊น? ๋ ๋๋ง ํผํฌ๋จผ์ค ๋๋ฌธ์ธ๊ฐ?)
๋ฌดํผ ์๋์ ๊ฐ์ด ํด๊ฒฐํ๋ค. ์๊ตฌ์ฌํญ์ ๋ง์ถ์ด, ๋ฒ์ ์ ํจ์ฑ ๊ฒ์ฌ๋ min์๋ง ํผ๋๋ฐฑ ๋ฌธ๊ตฌ๋ฅผ ๋์ฐ๋๋ก ํด์ผํ๋ฏ๋ก validate๋ min์ผ ๊ฒฝ์ฐ์๋ง ์ถ๊ฐํด์ฃผ๊ณ ,
useEffect๋ฅผ ํตํด max ๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ง๋ค min์ trigger ํด์ค๋ค.
useEffect(() => {
trigger(MIN);
}, [maxValue]);
...
{...register(inputKey, {
max: {
value: 100,
message: '100 ์ดํ์ ์ซ์๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์.',
},
...(inputKey === MIN && {validate: {
range: () =>
minValue <= maxValue ||
'์ง๋์จ ์์ ๊ตฌ๊ฐ์ ๋ ๊ตฌ๊ฐ๋ณด๋ค ํฌ์ง ์๊ฒ ์ค์ ํด ์ฃผ์ธ์.',
}}),
setValueAs: (v) => (v !== '' ? Number.parseInt(v, 10) : ''),
})}
๊ทธ ์ธ ํ๋ ๊ณ ๋ฏผ๋ค
- ํ๋์ ํ๋ ์์ ๋์์ ๋๊ฐ์ ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ๋์ธ ์ ์๋?
- ์ ๋ํด์ ์์ง ๋ต์ ์ฐพ์ง ๋ชปํ๋ค.
- ์ด๋ ํ ์ด์ ์์์ธ์ง input์ ์
๋ ฅํ ๊ฐ๋ค์ด ๋ฐ๋ก state๋ก ๊ด๋ฆฌ๋์ด์ผ ํ๋ค๊ณ ์๊ฐํ์์
- ๋ด๊ฐ ์ ์ฉํ๊ณ reset()์ ํธ์ถํ๋ ๋ฐ๋์ ๊ฐ์ด ๋ค ์๋ง์ง์ฐฝ์ด ๋์ด์ ๊ทธ๋ฌ์๋คโฆ
- ์ ์ฉํ๊ณ , reset ํ๊ณ , ๊ฐ๊ฐ์ input์ ์
๋ ฅ, ๋ณ๊ฒฝํ๋ ๊ณผ์ ์์ ๋ฌธ์ ๊ฐ ์๋ ๋ถ๋ถ์ด ๋์ํ์ง ์๊ฒ ๋๋ฉด์ ๊ธฐ์กด ์ฝ๋๋ฅผ ์ ์งํด์ผ๊ฒ ๋ค๋ ํ๋จ์ ๋ด๋ ธ๋ค.
- ์์ ์ ๋นจ๋ฆฌ ๋ง๋ฌด๋ฆฌํด์ผํ๋ค๋ ์ฝ๊ฐ์ ์๋ฐ๊ฐ๋ ์์๋ค.
- ์ง๊ธ ์๊ฐํด๋ณด๋ฉด ๋ด๊ฐ ์๋ชป ์ฝ๋ฉํ์๋ค..
- ๋ํ ๋น์์๋, react-hook-form์ ์ ์ฉํ๊ฒ ๋๋ฉด์ ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ์ ๋ง์กฑ์ํค๊ธฐ ์ํ ๋ค๋ฅธ ๋ถํ์ํ ์ฝ๋๋ค์ด ๋ ์ถ๊ฐ๋์๋ค๋ ์๊ฐ์ ์ฐ์ง ๋ง์์ผ๊ฒ ๋ค๋ ํ๋จ๋ ํ์๋ค.
- ex. react-query๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ๋ ๋ง์ ์ฝ๋๋ค
- ๊ทผ๋ฐ, ์ ์ง ๋ณด์ ์ธก๋ฉด์์ ๋ชจ๋๊ฐ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๊ณ ๋น ๋ฅด๊ฒ ์ดํดํ ์ ์๋ค๋ ์ ๋ ๊ฐ๊ณผํด์๋ ์๋๊ฒ ๋ค.
- ์๊ตฌ์ฌํญ์ ๋ฌ์ฑํ๊ธฐ ์ํ ๋์ฑ ์ถ๊ฐ์ ์ธ ์ฝ๋๋ค vs ๋ชจ๋๊ฐ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋น๋๊ธฐ ํจ์นญ์ ํด์จ๋ค (๋ค๋ฅธ ๊ฐ๋ฐ์๊ฐ ์ ์ง๋ณด์ ํ๋ฌ ์์ ๋ ์ด๊ธฐ ์ดํด๊ฐ ์ฝ๋ค)
- ๋ ํ๋์ ์๊ฐ, ๊ผญ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์์ ํด๊ฒฐํ ํ์๋ ์๋ค?
- ์ฌ๊ธฐ์ ๋ํด์๋ ๋ด ์๊ฐ์ ์์ง ํ์ ์ด ์๊ธด ํ๋ฐ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด์๋ ํด๋น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด์ ๊น๋ํ๊ฒ ํด๊ฒฐํ ์ ์๋ ๋ถ๋ถ์ ์์ฒด์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ๋ ๋ฐฉ๋ฒ์ด๋ผ๋ ์๊ฐ์ด ๋ค์๋ค.
- ๋ ์ด๋ฒ์ ๊ทธ๋ ๊ฒ ํด๊ฒฐํ๋ค.
์ต์ข ๊ตฌ์กฐ
trigger๋ฅผ ์ฐ๋ฉด์ ๋ง๋ฌด๋ฆฌํ๊ฒ๋ ์ค ์์์ผ๋, ํด๋น ๋ก์ง์ด ์ถ๊ฐ๋๋ฉด์ ์ฒ์ ์ค๊ณํ๋ ์ปดํฌ๋ํธ ๊ตฌ์กฐ๊ฐ ๊ต์ฅํ ๋ณต์กํ๊ฒ ๋ณํด๋ฒ๋ ธ๋ค. ํผ๊ณผ ์ง๋์จ ์ ๋ ฅํ๋ ์ธํ์ ๋ถ๋ฆฌํด์ ์ค๊ณํ์๋๋ฐ, ์์ชฝ ์ปดํฌ๋ํธ์์ ์ ํจ์ฑ ๊ฒ์ฌ, ์ํ ๋ณํ์ ๋ฐ๋ฅธ ๋ค๋ฅธ ์ํ๊ฐ ๋ณ๊ฒฝ ๋ฑ์ ๋ก์ง์ด ๋ถ์ฐ๋์ด ๋ฒ๋ ค์ ๊ฐ ์ปดํฌ๋ํธ์ ์ญํ ์ด ๋ชจํธํด์ง๊ณ ์ด๋ป๊ฒ ๋์ํ๋์ง ์ดํดํ๊ธฐ๊ฐ ์ด๋ ค์์ง ๊ฒ์ด๋ค.
- react-hook-form์ ์ฌ์ฉํ๋, errors์ isValid๋ย
FilterDropdown
์์ ์ํ๋ก์จ ๊ด๋ฆฌํ๋ค.- ํ ๊ตฌ์กฐ์์๋ ๊ฐ์ด ๋ณ๊ฒฝ๋จ์ ๋ฐ๋ผ ์ฌ๋ฌ input๋ค์ด ์์กด์ฑ์ ๊ฐ์ง๊ณ ์ฝํ์์ด react-hook-form์ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ ์ด์ ์ด ์๋ค๊ณ ํ๋จ
- ์ด์ ๋ฐ๋ผย
ProgressInput
์ ์ญํ ์ defaultValue๋ฅผ ๋ฐ์์ form์ register ํ๋ ๊ฒ์ผ๋ก ๋จ์ํ- ํ์ํ ๋ฉ์๋๊ฐ register ํ๋ ๋ฟ์ด๋ผ์ย
useFormContext
๋ฅผ ์ฐ์ง ์๋ ํธ์ด ์ฝ๋๊ฐ ๋ ๊ฐ๊ฒฐํ ๊ฒ ๊ฐ์ ์ ๊ฑฐ
- ํ์ํ ๋ฉ์๋๊ฐ register ํ๋ ๋ฟ์ด๋ผ์ย
FilterDropdown
์์ฑํ ์ฝ๋ ์ค์์, ์ปจ์ ์ ํ์ธํ ์ ์๋๋ก ์๋ผ์ด
import React, { useState, useEffect } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { checkValidation, checkIsValid } from '../../utils/filterUtils';
const ProgressInput = ({ defaultValue, inputId, register, errors = [] }) => {
const isValid = errors.length === 0;
return (
<div className="w-100">
<input
defaultValue={defaultValue}
id={inputId}
{...register(inputId, {
setValueAs: (v) => (v !== '' ? Number.parseInt(v, 10) : ''),
})}
/>
</div>
);
};
function FilterDropdown() {
const [errors, setErrors] = useState({});
const [isValid, setIsValid] = useState(true);
const { register, handleSubmit, reset, setValue, control } = useForm({
mode: 'onChange',
defaultValues: {
minValue: minProgress ?? 0,
maxValue: maxProgress ?? 100,
showMaxPercent: minProgress === 100 && maxProgress === 100,
},
reValidateMode: 'onChange',
});
const min = useWatch({ control, name: MIN });
const max = useWatch({ control, name: MAX });
const showMax = useWatch({ control, name: SHOW_MAX });
useEffect(() => {
if (showMax) {
setValue(MIN, 100);
setValue(MAX, 100);
} else {
setValue(MIN, min);
setValue(MAX, max);
}
}, [showMax]);
useEffect(() => {
// iunput์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์์ฒด์ ์ผ๋ก ๊ตฌํํ ์ ํจ์ฑ ๊ฒ์ฌ ์ํ
// ์์์๋ ์ ์ ์๋ฏ์ด, input 3๊ฐ๊ฐ ๋ชจ๋ ๊น์ ์์กด์ฑ์ ๊ฐ์ง๊ณ ์์
// react-hook-form์์ ๋จ์ผ input์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ๋ ์ฉ์ดํ๋, ์์ ๊ฐ์ ์ํฉ์์ ๋ง์ง ์๋ค๊ณ ํ๋จ
setErrors((prev) => ({
...prev,
[MIN]: checkValidation(min, max, errors[MIN]),
[MAX]: checkValidation(max, max, errors[MAX]),
}));
if (min === 100 && max === 100) {
setValue(SHOW_MAX, true);
} else {
setValue(SHOW_MAX, false);
}
}, [min, max]);
useEffect(() => {
setIsValid(checkIsValid(errors));
}, [errors]);
return (
<Dropdown isOpen={isOpen} toggle={toggle}>
<DropdownToggle>
...
</DropdownToggle>
<DropdownMenu>
<Form id="progress-filter-form" onSubmit={handleSubmit(handleApply)}>
<ProgressInput
defaultValue={min}
inputId={MIN}
register={register}
errors={errors[MIN]}
/>
<ProgressInput
defaultValue={max}
inputId={MAX}
register={register}
errors={errors[MAX]}
/>
<Label className="ml-3" check>
<input
className="form-check-input"
name={SHOW_MAX}
type="checkbox"
{...register(SHOW_MAX)}
/>
<div className="ml-2">์ง๋์จ 100%๋ง ๋ณด๊ธฐ</div>
</Label>
</Form>
...
</DropdownMenu>
</Dropdown>
);
}
export default FilterDropdown;
utils
import _find from 'lodash/find';
import _remove from 'lodash/remove';
/**
* @param {*} value Number
* @param {*} maxValue Number
* @param {*} errorMessages Array of {type: '', message: ''}
* @returns Array of {type: '', message: ''}
*/
const ERROR_TYPE_MIN = 'min';
const ERROR_TYPE_MAX = 'max';
const ERROR_TYPE_RANGE = 'range';
export const checkValidation = (value, maxValue, errors = []) => {
const currentErrors = errors;
const hasMinError = _find(currentErrors, { type: ERROR_TYPE_MIN });
if (value < 0) {
!hasMinError &&
currentErrors.push({
type: ERROR_TYPE_MIN,
message: '0 ์ด์์ ์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.',
});
} else {
_remove(currentErrors, { type: ERROR_TYPE_MIN });
}
const hasMaxError = _find(currentErrors, { type: ERROR_TYPE_MAX });
if (value > 100) {
!hasMaxError &&
currentErrors.push({
type: ERROR_TYPE_MAX,
message: '100 ์ดํ์ ์ซ์๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์.',
});
} else {
_remove(currentErrors, { type: ERROR_TYPE_MAX });
}
if (value > maxValue) {
const hasRangeError = _find(currentErrors, { type: ERROR_TYPE_RANGE });
!hasRangeError &&
currentErrors.push({
type: ERROR_TYPE_RANGE,
message: '์ง๋์จ ์์ ๊ตฌ๊ฐ์ ๋ ๊ตฌ๊ฐ๋ณด๋ค ํฌ์ง ์๊ฒ ์ค์ ํด ์ฃผ์ธ์.',
});
} else {
_remove(currentErrors, { type: ERROR_TYPE_RANGE });
}
return currentErrors;
};
/**
* @param {*} errors Object
* {
* min: [ {type: '', message: ''}, ... ],
* max: [ {type: '', message: ''}, ... ],
* ...
* }
* @returns Boolean
*/
export const checkIsValid = (errors = {}) => {
const allErrors = Object.values(errors);
const hasError =
allErrors.filter((eachErrors) => eachErrors.length > 0).length > 0;
return !hasError;
};
์ป์ ์ด์
setValueAs: (v) => (v !== '' ? Number.parseInt(v, 10) : '')
ย ๋ฅผ ํตํด ์ ๋ ฅ๊ฐ์ด ์ซ์์์ ๋ณด์ฅํ ์ ์๊ฒ ๋๋ฉด์ input value์ด string์ผ ๊ฒฝ์ฐ๋ ๊ณ ๋ คํ๊ธฐ ์ํด ์ถ๊ฐ๋ ์ฝ๋๋ค์ ์ญ์ ํ ์ ์์๋ค.
๊ฒฐ๋ก
์๋ก์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฒ์ ์ฌ์ฉํ ๋๋ ์ค์ ๋ก ์ ์ฉ๋ ์ฝ๋๋ฅผ ๋ณด๋ฉฐ ์ฌ์ฉ๋ฒ์ ๋น ๋ฅด๊ฒ ์ตํ๋ ๊ฒ๋ ์ค์ํ์ง๋ง, ๊ณต์ ๋ฌธ์๋ฅผ ์ ๋ ํ๋ ์๊ฐ์ด ๊ผญ ํ์ํ๋ค. ๋, ๊ผญ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด์๋ง ๋ชจ๋ ๊ฒ์ ํด๊ฒฐํ๋ ค๊ณ ํ์ง ๋ง์. ๊ทธ์ ํ๋์ ํธ๋ฆฌํ ๋๊ตฌ์ผ ๋ฟ์ด๋ค.
- ์ง๊ธ ๋ํํ ์์ ํ ํ์ํ ๋๊ตฌ๊ฐ ์๋๋ผ๋ฉด, ํ์ํ ๋ถ๋ถ๋ง ์ฌ์ฉํ๊ณ ์๋ ๋ถ๋ถ์ ๋ด๊ฐ ๋ง๋ค์ด์ ์ฌ์ฉํ ์ ์๋ค๋ ์๊ฐ
๊ทธ๋ฆฌ๊ณ , ํญ์ ์๊ฐํด์ผ ํ ๊ฒ
- ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ด๋ค ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋์จ ๊ฒ์ธ๊ฐ?
- ์ง๊ธ ๋ด๊ฐ ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์ ์ ๋ํ ์ ํฉํ ํด๊ฒฐ์ฑ ์ธ๊ฐ?
์ ์ง๋ฌธ์ ๊ผญ ๋จผ์ ํด๋ณด๋๋ก ํ์. ์ด์ ๋ ๋จ์ํ ๋น ๋ฅด๊ฒ ๋์ํ๋ ์ฝ๋๋ฅผ ๋ง๋ค์ด ๋ด๋ ๊ฒ
์ ๊ทธ์น๋ฉด ์๋๊ณ , ์ ์ง ๋ณด์๊ฐ ์ฌ์ด ์ฝ๋, ์ ๊ฒ ์ง์ ํด๊ฒฐํ ์ ์๋ ์ข์ ๊ตฌ์กฐ์ ์ฝ๋
๋ฅผ ์๊ฐํด๋ด์ผ ํ๋ค.
# ์นดํ ๊ณ ๋ฆฌ
- BOJ 36
- Algorithm 12
- CodingTest 11
- Web 9
- Javascript 8
- Vue 7
- React 7
- DBProject 4
- Python 3
- Tech-interview 3
- Express 3
- Next 3
- Github 2
- Django 2
- C 1
- C++ 1
- WebGame 1