react-hook-form 에러
본문
1. register에 선언한 에러메시지가 화면에 렌더링이 되지 않습니다 (동작은 합니다)
2. 제출 버튼을 조건에 만족하지 않으면 비활성화 시켜놓았습니다 . 하지만 제출 버튼을 눌러야만 에러메시지가 뜨는데 실시간으로 뜨게 할수 는 없을까요?
// app.js
import { useEffect, useState } from "react";
import styled from "styled-components";
import User from "./components/user";
import { useForm } from "react-hook-form";
const Wrapper = styled.div`
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
`;
const Box = styled.div``;
const Form = styled.form`
width: 400px;
margin-bottom: 20px;
`;
const AddUser = styled.button`
margin: 0px 8px 20px 0;
font-size: 13px;
cursor: pointer;
border: 2px solid;
width: 100px;
height: 33px;
background: none;
&:hover {
background: black;
color: white;
border: transparent;
}
`;
const Confirm = styled(AddUser)`
pointer-events: ${(props) => (props.disabled ? "none" : "auto")};
`;
const DataFields = styled.div`
background: #eee;
padding: 10px;
font-size: 13px;
`;
const SubmitData = styled.p`
margin: 0;
`;
function App() {
const [userBox, setUserBox] = useState([{ name: "", password: "" }]);
const { handleSubmit, register:formRegister, formState } = useForm();
const onAddUser = () => {
const addForm = [...userBox, { name: "", password: "" }];
setUserBox(addForm);
};
const onDeleteUser = (index) => {
if (userBox.length === 1) {
alert("적어도 한개 이상의 정보란은 필수입니다");
return;
}
const deleteForm = [
...userBox.slice(0, index),
...userBox.slice(index + 1),
];
setUserBox(deleteForm);
};
const onValid = (data) => {
setUserBox(data.userBox);
};
useEffect(() => {
console.log("userBox changed:", userBox);
}, [userBox]);
return (
<Wrapper>
<Box>
<Form onSubmit={handleSubmit(onValid)}>
{userBox.map((_, index) => (
<User
key={index}
counter={index + 1}
onDeleteUser={onDeleteUser}
index={index}
register={formRegister}
formState={formState}
userBox={userBox}
/>
))}
<AddUser onClick={() => onAddUser()}>Add User</AddUser>
<Confirm type="submit" disabled={!formState.isValid}>
Confirm
</Confirm>
{formState.isSubmitSuccessful &&
userBox.map((user, i) => (
<DataFields key={i}>
<SubmitData><b>Name</b> : {user.name}</SubmitData>
<SubmitData><b>Password</b> : {user.password}</SubmitData>
</DataFields>
))}
</Form>
</Box>
</Wrapper>
);
}
export default App;
===============================
// user.js
import styled from "styled-components";
import Input from "./input";
const Wrapper = styled.div``;
const FormWrap = styled.div`
border: 2px solid black;
padding: 10px;
margin-bottom: 10px;
`;
const TitleBox = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
`;
const Title = styled.h2`
margin: 0;
`;
const Delete = styled.button`
cursor: pointer;
border: 2px solid;
background: none;
font-weight: 600;
`;
const Error = styled.span`
color: red;
font-size: 13px;
`;
const Label = styled.label`
display: block;
`;
const InputBox = styled.input`
width: 100%;
height: 25px;
box-sizing: border-box;
`;
function User({ counter, onDeleteUser, index, register, formState }) {
return (
<Wrapper>
<FormWrap>
<TitleBox>
<Title>User - {counter - 1}</Title>
<Delete onClick={() => onDeleteUser(index)}>x</Delete>
</TitleBox>
<Input
register={register(`userBox[${index}].name`, {
required: "※ 아이디가 입력되지 않았어요",
minLength: {
value: 3,
message: "※ 아이디는 3글자 이상 필수입니다",
},
})}
name="name"
label="Name"
type="text"
/>
<Error>{formState.errors[`userBox[${index}].name`]?.message}</Error>
<Input
register={register(`userBox[${index}].password`, {
required: "※ 비밀번호가 입력되지 않았어요",
minLength: {
value: 6,
message: "※ 비밀번호는 6글자 이상 필수입니다",
},
})}
name="password"
label="Password"
type="password"
/>
<Error>{formState.errors[`userBox[${index}].password`]?.message}</Error>
</FormWrap>
</Wrapper>
);
}
export default User;
=================================
// input.js
import styled from "styled-components";
const Label = styled.label`
display: block;
`;
const InputBox = styled.input`
width: 100%;
height: 25px;
box-sizing: border-box;
`;
function Input({ register, name, type, label }) {
return (
<>
<Label htmlFor={name}>{label}</Label>
<InputBox id={name} type={type} {...register} />
</>
);
}
export default Input;