use-form
use-form
useForm 훅은 @mantine/form 패키지의 핵심으로, 폼 상태를 관리하고 검증과 제출을 처리해요. 다른 어떤 라이브러리에도 의존하지 않아 @mantine/core 입력 없이도 단독으로 사용할 수 있어요. 주요 API를 하나씩 설명해 드릴게요.
출처: 문서
본문
설치
@mantine/form 패키지는 다른 어떤 라이브러리에도 의존하지 않아요. @mantine/core 입력과 함께 써도 되고, 없이 써도 돼요:
yarn add @mantine/form
사용법
import { Button, Checkbox, Group, TextInput } from '@mantine/core';
import { useForm } from '@mantine/form';
function Demo() {
const form = useForm({
mode: 'uncontrolled',
initialValues: {
email: '',
termsOfService: false,
},
validate: {
email: (value) => (/^\S+@\S+$/.test(value) ? null : 'Invalid email'),
},
});
return (
<form onSubmit={form.onSubmit((values) => console.log(values))}>
<TextInput
withAsterisk
label="Email"
placeholder="[email protected]"
key={form.key('email')}
{...form.getInputProps('email')}
/>
<Checkbox
mt="md"
label="I agree to sell my privacy"
key={form.key('termsOfService')}
{...form.getInputProps('termsOfService', { type: 'checkbox' })}
/>
<Group justify="flex-end" mt="md">
<Button type="submit">Submit</Button>
</Group>
</form>
);
}
API 개요
아래 예제들은 모두 다음 예시 useForm 훅을 사용해요:
import { useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
path: '',
path2: '',
user: {
firstName: 'John',
lastName: 'Doe',
},
fruits: [
{ name: 'Banana', available: true },
{ name: 'Orange', available: false },
],
accepted: false,
},
});
값 (Values)
// get the current form values
form.getValues();
// Set all form values
form.setValues(values);
// Set all form values using the previous state
form.setValues((prev) => ({ ...prev, ...values }));
// Set the value of a single field
form.setFieldValue('path', value);
// Set the value of a nested field
form.setFieldValue('user.firstName', 'Jane');
// Resets form values to `initialValues`,
// clears all validation errors,
// resets touched and dirty state
form.reset();
// Reset the field at `path` to its initial value
form.resetField('path');
// Sets initial values, used when the form is reset
form.setInitialValues({ values: 'object' });
목록 항목 (List items)
// Inserts the given list item at the specified path
form.insertListItem('fruits', { name: 'Apple', available: true });
// An optional index may be provided to specify the position in a nested field.
// If the index is provided, the item will be inserted at the given position.
// If the index is larger than the current list, the element is inserted at the last position.
form.insertListItem('fruits', { name: 'Orange', available: true }, 1);
// Removes the list item at the specified path and index.
form.removeListItem('fruits', 1);
// Replaces the list item at the specified path and index with the given item.
form.replaceListItem('fruits', 1, { name: 'Apple', available: true });
// Swaps two items of the list at the specified path.
// You should make sure that there are elements at the `from` and `to` index.
form.reorderListItem('fruits', { from: 1, to: 0 });
검증 (Validation)
import { useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
initialValues: {
email: '',
user: {
firstName: '',
lastName: '',
},
},
validate: {
email: (value) => (value.length < 2 ? 'Invalid email' : null),
user: {
firstName: (value) =>
value.length < 2
? 'First name must have at least 2 letters'
: null,
},
},
});
// Validates all fields with the specified `validate` function or schema, sets form.errors
await form.validate();
// Validates a single field at the specified path, sets form.errors
await form.validateField('user.firstName');
// Works the same way as form.validate but does not set form.errors, returns Promise<boolean>
await form.isValid();
await form.isValid('user.firstName');
// true while any async validation is running
form.validating;
// true while async validation is running for a specific field
form.isValidating('email');
오류 (Errors)
Form errors guide. 검증 오류는 정의된 검증 규칙을 위반했을 때, useForm 속성에 initialErrors를 지정했을 때, 또는 검증 오류를 수동으로 설정했을 때 발생해요:
// get the current errors state
form.errors;
// Set all errors
form.setErrors({ path: 'Error message', path2: 'Another error' });
// Set an error message at the specified path
form.setFieldError('user.lastName', 'No special characters allowed');
// Clears all errors
form.clearErrors();
// Clears the error of the field at the specified path
form.clearFieldError('path');
onReset과 onSubmit
폼 onSubmit과 onReset 이벤트 핸들러를 위한 래퍼 함수예요. onSubmit 핸들러는 두 번째 인자로 검증 실패 시 오류 객체와 함께 호출될 함수를 받아요:
import { useForm } from '@mantine/form';
function Demo() {
const form = useForm({ mode: 'uncontrolled' });
const handleSubmit = (values: typeof form.values) => {
console.log(values);
};
return (
<>
{/* Supply handle submit as a single argument to receive validated values */}
<form onSubmit={form.onSubmit(handleSubmit)} />
{/* Supply a second argument to handle errors */}
<form
onSubmit={form.onSubmit(
(values, event) => {
console.log(
values, // <- form.getValues() at the moment of submit
event // <- form element submit event
);
},
(validationErrors, values, event) => {
console.log(
validationErrors, // <- form.errors at the moment of submit
values, // <- form.getValues() at the moment of submit
event // <- form element submit event
);
}
)}
/>
{/* form.onReset calls form.reset */}
<form onReset={form.onReset}></form>
</>
);
}
onSubmitPreventDefault 옵션
기본적으로 폼 onSubmit 핸들러에서 event.preventDefault()가 호출돼요. 이 동작을 바꾸려면 useForm 훅에 onSubmitPreventDefault 옵션을 전달할 수 있어요. 다음 값을 가질 수 있어요:
always(기본값) — 항상event.preventDefault()호출never— 절대event.preventDefault()호출하지 않음validation-failed— 검증이 실패한 경우에만event.preventDefault()호출
import { useForm } from '@mantine/form';
const form = useForm({
mode: 'uncontrolled',
onSubmitPreventDefault: 'never',
});
터치와 dirty (Touched and dirty)
// Returns true if the user interacted with any field inside the form in any way
form.isTouched();
// Returns true if the user interacted with the field at the specified path
form.isTouched('path');
// Set all touched values
form.setTouched({ 'user.firstName': true, 'user.lastName': false });
// Clears the touched status of all fields
form.resetTouched();
// Returns true if form values are not deep equal to initialValues
form.isDirty();
// Returns true if the field value is not deep equal to initialValues
form.isDirty('path');
// Sets the dirty status of all fields
form.setDirty({ 'user.firstName': true, 'user.lastName': false });
// Clears the dirty status of all fields, saves form.values snapshot
// After form.resetDirty is called, form.isDirty will compare
// form.getValues() to the snapshot instead of initialValues
form.resetDirty();
UseFormReturnType
UseFormReturnType는 form을 다른 컴포넌트에 prop으로 전달할 때 사용할 수 있어요:
import { TextInput } from '@mantine/core';
import { useForm, UseFormReturnType } from '@mantine/form';
interface FormValues {
name: string;
occupation: string;
}
function NameInput({
form,
}: {
form: UseFormReturnType<FormValues>;
}) {
return (
<TextInput
key={form.key('name')}
{...form.getInputProps('name')}
/>
);
}
function OccupationInput({
form,
}: {
form: UseFormReturnType<FormValues>;
}) {
return (
<TextInput
key={form.key('occupation')}
{...form.getInputProps('occupation')}
/>
);
}
function Demo() {
const form = useForm<FormValues>({
mode: 'uncontrolled',
initialValues: { name: '', occupation: '' },
});
return (
<>
<NameInput form={form} />
<OccupationInput form={form} />
</>
);
}
더 알아보기 (Learn more)
- Get started — 시작하기
- use-field — use-field 훅