Sign-up-form 에 있는 input 부분을 따로 떼서 탬플릿으로 만들어 보자.
components 폴더 안에
form-input 폴더와 jsx, scss 파일을 만든다.
sign-up-form.jsx에서 첫 번째 input 세트를 form-input.jsx로 옮긴다.
[방법 1 ] 기본 props 사용
form-input.jsx 로 내용을 붙여넣기 했다.
input의 attribute를 일일이 적었다.
form-input.jsx
sign-up-form 에서 FormInput 태그로 바꿨다.
[방법 2] ...otherProps 사용 - 간단 !
sign-up-form 에서 FormInput 태그를 그대로 쓰고
input-form을 더 간단하게 만들 수 있다.
label은 다른 태그라 따로 써주고, spread operator를 사용해서
FormInput에 있는 모든 속성을 props로 가져온다.
const FormInput = ({ label, ...otherProps }) => {
return (
<div>
<label>{label}</label>
<input {...otherProps} />
</div>
)
}
export default FormInput;
파일을 import 한 후
sign-up-form으로 가서 FormInput 탬플릿을 전부 적용 시킨다.
import { useState } from 'react';
import { createAuthUserWithEmailAndPassword, createUserDocumentFromAuth } from '../../utils/firebase/firebase';
import FormInput from '../form-input/form-input';
const defaultFormFields = {
displayName: '',
email: '',
password: '',
confirmPassword: ''
}
const SignUpForm = () => {
const [formFields, setFormFields] = useState(defaultFormFields);
const { displayName, email, password, confirmPassword } = formFields;
const resetFormFields = () => {
setFormFields(defaultFormFields)
}
const handleSubmit = async (event) => {
event.preventDefault();
if (password !== confirmPassword) {
alert('passwords do not match');
return;
}
try {
const { user } = await createAuthUserWithEmailAndPassword(email, password);
await createUserDocumentFromAuth(user, { displayName });
resetFormFields();
} catch (error) {
if (error.code === 'auth/email-already-in-use') {
alert('Cannot create user, email alredy in use');
} else {
console.log('user creation encountered an error', error);
}
}
}
console.log(formFields)
const changeHandler = (event) => {
const { name, value } = event.target;
setFormFields({ ...formFields, [name]: value })
}
return (
<div>
<h1>Email Sign Up Component</h1>
<form onSubmit={handleSubmit}>
<FormInput
label='display Name'
type='text'
required
onChange={changeHandler}
name='displayName'
value={displayName}
/>
<FormInput
label='Email'
type='email'
required
onChange={changeHandler}
name='email'
value={email}
/>
<FormInput
label='Password'
type='password'
required
onChange={changeHandler}
name='password'
value={password}
/>
<FormInput
label='Confirm Password'
type='password'
required
onChange={changeHandler}
name='confirmPassword'
value={confirmPassword}
/>
<button type='submit'>Sign Up</button>
</form>
</div>
)
}
export default SignUpForm;
잘 나오는 것을 볼 수 있다.
[방법 3] input 속성을 하나의 오브젝트로
input 속성 부분을 따로 오브젝트 덩어리로 만들어 사용할 수 있다.
...otherProps 대신 InputOptions 을 사용해서
form-input.jsx 에서도 바꿔준다.
잘 나오는 것을 볼 수 있다.
FormInput Styles
form-input.scss 파일을 jsx 파일에 연결해 준 후
FormInput에 클래스를 추가해 준다.
label의 클래스는 다이나믹으로 해준다.
otherProps 중에서 value 의 length > 0 또는 입력이 들어왔다는 것이라 > 0 생략 가능
true 일 때 className: 'shink', false 일 때 className이 없다.
line5 : 'shink' 아니고 'shrink' 임. 오타
여기에 className을 하나 더 추가한다.
모든 className을 보면 다음과 같다.
여기서 label 태그 전체를 { }로 감싼 후
&& 사용해서 label이 있으면 label 태그가 생기도록 한다.
form-input.scss 의 내용을 채운다.
$sub-color: grey;
$main-color: black;
@mixin shrinkLabel {
top: -14px;
font-size: 12px;
color: $main-color;
}
.group {
position: relative;
margin: 45px 0;
.form-input {
background: none;
background-color: white;
color: $sub-color;
font-size: 18px;
padding: 10px 10px 10px 5px;
display: block;
width: 100%;
border: none;
border-radius: 0;
border-bottom: 1px solid $sub-color;
margin: 25px 0;
&:focus {
outline: none;
}
&:focus ~ .form-input-label {
@include shrinkLabel();
}
}
input[type='password'] {
letter-spacing: 0.3em;
}
.form-input-label {
color: $sub-color;
font-size: 16px;
font-weight: normal;
position: absolute;
pointer-events: none;
left: 5px;
top: 10px;
transition: 300ms ease all;
&.shrink {
@include shrinkLabel();
}
}
}
<input> 태그가 밑에 있으니 에러가 난다.
<input> 태그를 label 위로 올려준다.
import './form-input.scss';
const FormInput = ({ label, ...otherProps }) => {
return (
<div className='group'>
<input className='form-input' {...otherProps} />
{label && (<label
className={
`${otherProps.value.length ? 'shrink' : ''}
form-input-label`
}>{label}</label>)}
</div>
)
}
export default FormInput;
잘 되는 것을 볼 수 있다.
댓글