본문 바로가기
React/E-commers App

의류 쇼핑몰 20 | Input을 탬플릿으로 만들기

by CodeMia 2022. 6. 16.

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;

 

잘 되는 것을 볼 수 있다. 

 

 

댓글