구조가 유사하게 반복된다면 이미 만들어진 컴포넌트로 재사용을 하여 줄일 수 있다.
비슷한데 다른부분을 컴포넌트화를 시켜서 변화를 준다.
// before -> 두 개의 내용을 표현하기 위한 두 개의 파일
isMyID ? <ProfileMyID /> : <ProfileOtherID />
// after -> 두 개의 내용을 표현하기 위한 하나의 파일
const MY_ID = '12345'
const OTHER_ID = '54321'
isMyID ? <Profile userID={MY_ID} /> : <Profile userID={OTHER_ID} />
isMyID가 ture이거나 false일때 컴포넌트가 보여지게 할 수도 있었다
하지만 propfile이라는 컴포넌트를 만들고 여기에 필요한 데이터를 props로 내려보내준다.
export default class Modal extends Component {
state = {
clickedType: "",
};
handleClick = (e) => {
this.setState({ clickedType: e.target.innerText });
};
render() {
return (
<div className="Modal">
<Form
format={
this.state.clickedType === "로그인" ? signInProps : signUpProps
}
handleClick={this.handleClick}
/>
</div>
);
}
}
const signUpProps = {
type: "signUp",
text: "회원가입",
data: [
{
type: "name",
text: "이름",
},
{
type: "email",
text: "이메일",
},
{
type: "password",
text: "비밀번호",
},
],
};
const signInProps = {
type: "signIn",
text: "로그인",
data: [
{
type: "email",
text: "이메일",
},
{
type: "password",
text: "비밀번호",
},
],
};
Modal 부모컴포넌트에선 state값으로 clickedType을 빈스트링으로 설정한다.
그리고 함수 handleClick 가 실행 될때마다 setState로 clickedType에
e.target.innerText 로 state값으로 저장해준다.
handleClick 함수는 Form 이라는 컴포넌트에 handleClICK 이라는 이름으로 this.handleClick 함수를 props 로 넘겨주고, 그 이외에 format 은 clickedType에 들어오는 스트링이 로그인 과 같다면
signInProps 를 props로 보내고 그게 아니라면 signUpProps 를 props로 내보낸다.
그 아래 객체 형태로 로그인과 회원가입을 변수로 선언해줬다.
render() {
const { format } = this.props;
return (
<FormLayout>
<h2>{format.text}</h2>
<div>
{format.data.map((input, idx) => (
<Input key={idx} type={input.type} text={input.text} />
))}
</div>
<Button value={format.text} />
{format.type === "signUp" && (
<p className="isAlreadyLogin">
이미 가입하셨나요? <span>로그인</span>
</p>
)}
</FormLayout>
);
}
실질적으로 render하고 있는 컴포넌트.
form 컴포넌트는 props에 따라서
input과 button, text를 다르게 설정해주고 있다.
modal컴포넌트에서 format으로 받아온 props(signUpProps 또는 signInProps) 를 data 에 접근하여 map을 돌리며 배열형태를 하나씩 뿌려주면서 input을 render 해주고 있다. (인자 input 들어오면서 type과 text에 접근하여 데이터를 뿌린다!)
render() {
const { type, text } = this.props;
return (
<div className="Input">
<div className="inputWrapper">
<input type={type} placeholder={text} />
</div>
</div>
);
}