컴포넌트가 무엇인지 궁금하다면 아래 링크 클릭하기!
컴포넌트 What is Component?
UI 일부가 여러 번 사용되거나, UI 일부가 자체적으로 복잡한 경우에는 별도의 컴포넌트로 만드는게 좋습니다. -React 공식문서-
두 레이아웃에서 반복적으로 사용되는 요소와 변화되는 요소들을 찾을 수 있다.
변화하는 부분들이 있다고 하더라도 매번 다른 코드로 처리할 필요 없이 컴포넌트화 하여 사용할 수 있다.
공통적으로 적용되는 부분은
다른 부분
import React from "react";
import Form from "./Components/Form";
import "./Modal.scss";
export default function Modal() {
return (
<div className="modal">
<Form type="signIn" title="로그인" />
<Form type="signUp" title="회원가입" />
</div>
);
}
우선 두 가지의 Modal창이 필요하니 동일한 컴포넌트를 사용해서 바뀔 부분만 수정한다.
상수 데이터를 사용하여 각 Modal창에서 사용할 정적인 데이터를 넘겨준다.
상수 데이터로 각각의 모달 창에 데이터 부여하기
import React from "react";
import Form from "./Components/Form";
import "./Modal.scss";
export default function Modal() {
return (
<div className="modal">
<Form type="signIn" title="로그인" inputData={SIGNIN_DATA} />
<Form type="signUp" title="회원가입" inputData={SIGNUP_DATA} />
</div>
);
}
//상수 데이터 (정적인 데이터, 변하지 않는 데이터)
//로그인에 해당하는 데이터
const SIGNIN_DATA = [
{
type: "email",
text: "이메일",
},
{
type: "password",
text: "비밀번호",
},
];
//회원가입에 해당하는 데이터
const SIGNUP_DATA = [
{
type: "name",
text: "이름",
},
{
type: "email",
text: "이메일",
},
{
type: "password",
text: "비밀번호",
},
];
Modal
에서 자식인 <Form/>
컴포넌트에 넘겨주는 데이터는type
이라는 이름으로 "signIn", "signUp" 이라는 문자열title
이라는 이름으로 "로그인", "회원가입" 이라는 문자열inputData
라는 이름으로 {SIGNIN_DATA}
와 {SIGNUP_DATA}
상수 데이터 export default function Form({ type, title, inputData }) {
return (
<FormLayout>
<div className="form">
<h2>{title}</h2>
<div>
{inputData.map((input, idx) => (
<Input key={idx} type={input.type} text={input.text} />
))}
</div>
<Button value={title} />
{type === "signUp" && (
<p className="isAlreadyLogin">
이미 가입하셨나요? <span className="linkBtn">로그인</span>
</p>
)}
</div>
</FormLayout>
);
}
map 함수로 input창을 속성과 함께 생성하기
위에서 <Form/>
컴포넌트에 넘겨준 props
를 props
안에 있는 객체를 구조분해할당하여 {type, title, inputData}
로 받는다.
Form.js 안에는 <FormLayOut/>
컴포넌트가 있다. 이는 Modal창 틀을 구성하고 있다.
Modal 창의 제목을 부여하기 위해서 <h2>{title}</h2>
를 작성한다.
inputData
는 배열이기 때문에 map 함수를 통해 <Input/>
컴포넌트에 props
로 넘겨준다.
input
창이 생성된다.key
는 값을 부여하는 역할이며 map 함수의 가장 상위 태그에 필수로 작성한다.type
으로는 상수데이터에 명시했던 {type}
을 받아온다.text
에 또한 상수데이터에 명시했던 {text}
를 받아온다.따라서 로그인 창에는 2개의 input
창이 생성되고, 회원가입 창에는 3개의 input
창이 생성된다.
<Button/>
컴포넌트에는 로그인 창과 회원가입 창마다 명시된 text가 다르기 때문에 value
라는 이름으로 각각의 {title}
을 넘겨준다.
Modal 창의 가장 하단에 적혀있는 text를 구현하기 위해서 조건부 렌더링(&&)을 사용하여 type
이 "signup"이라면 아래의 태그를 출력하라는 조건을 추가한다.
처음 Modal.js에서 type
이라는 이름으로 "signUp", "signIn"을 각각 넘겨주었다. 아래의 텍스트는 회원가입 즉, "signup"을 할 때만 필요한 text
이므로 type
이 "signUp"일 때만 아래의 텍스트가 나타나게 한다.
import React from "react";
import "./Input.scss";
export default function Input({ type, text }) {
return (
<div className="input">
<div className="inputWrapper">
<input name={type} type={type} placeholder={text} />
</div>
</div>
);
}
Form.js로부터 넘겨 받은 props
를 구조분해할당하여 input.js에서 {type, text}
로 받는다.
<input>
태그 안에 필요한 속성을 작성한다.
name
속성은 추후 데이터가 서버로 전송될 때 해당 input
의 이름이 무엇이었는지 명시해주기 위해 작성한다.type
이 password라면 ••••• 표시로 정보 유출을 방지할 수 있다.placeholder
에 text
데이터가 부여되면서 input
창에 작성하기 전 사용자에게 어떤 정보를 작성해야 하는지 힌트를 준다.import React from "react";
import "./Button.scss";
export default function Button(props) {
return <div className="button">{props.value}</div>;
}
Form.js에서 <Button/>
컴포넌트에 value 이름으로 {title}
을 넘겨주었다.
하나의 props
를 넘겨주었기 때문에 굳이 구조분해할당을 할 필요는 없다. 따라서 props
라고 작성하여 부여할 때 value 객체에 접근하면 된다.
물론 이렇게 작성해도 동일하게 출력된다.
export default function Button({ value }) {
return <div className="button">{value}</div>;
}
import React from "react";
import "./FormLayout.scss";
export default function FormLayout(props) {
return (
<div className="formLayout">
<header>
<div className="logo" />
</header>
{props.children}
</div>
);
}
Modal창의 전체적인 틀을 구성하고 있는 <FormLayOut/>
컴포넌트에는 Form.js에서 작성된 모든 요소들을 감싸고 있었다.
따라서 우리가 작성한 모든 컴포넌트와 요소들이 <FormLayOut/>
컴포넌트에 자식으로 들어가 있다.
하지만
위의 이미지에서 로고는 두 Modal 창 모두 가지고 있어야 하며 변하지 않는 요소이다.
따라서 로고는 정적인 데이터를 따로 분리하기 위해서 <FormLayOut/>
컴포넌트를 따로 만든 것이다.
{props.children}
은 무엇이며 어떻게 사용할까?원래 props
는 부모에서 자식에게 넘겨주는 데이터라고 알고있다.
하지만 Form.js에서 FormLayOut 컴포넌트에 아무런 props를 넘겨주지 않았는데 왜 이렇게 작성할까?
export default function FormLayout(props){};
props를 console에 찍어보면 Form.js에서 <FormLayout><FormLayout/>
안에 작성했던 데이터들이 담겨있다.
props
는 결국 <FormLayout><FormLayout/>
안에 있는 데이터를 가지고 있다.
보통 컴포넌트를 생성할 때 <FormLayout/>
self-closing을 하지만 열고 닫는 태그 안에 요소들을 넣어주면 props.children
으로 값들을 불러올 수 있다.
정적인 데이터와 동적인 데이터를 분리해서 관리할 수 있기 때문이다. 유지보수 용이
위에서 언급했듯, <FormLayout><FormLayout/>
안에 있는 요소들을 동적인 데이터이며 동적인 데이터를 수정할 때는 안에서 수정하면 된다.
만약 로고처럼 동적인 데이터를 수정할 때는 FormLayout.js에 와서 정적인 데이터만 수정하면 된다.