리액트 컴포넌트
리액트 컴포넌트에서의 입력은 `props`, 출력은 리액트 엘리먼트.
역할: `어떠한 속성들을 입력으로 받아서 그에 맞는 리액트 엘리먼트를 생성하여 리턴해주는 것
컴포넌트의 이름은 항상 대문자로 시작해야 한다.
Props
리액트 컴포넌트의 속성
컴포넌트에 전달할 다양한 정보를 담고 있는 자바스크립트 객체
Props를 사용하지 않는다면?
데이터 흐름의 혼란
props는 부모 컴포넌트 -> 자식 컴포넌트로 데이터를 전달하는 기본적인 방식이므로, props를 사용하지 않으면 데이터가 어디서 오는지, 어디로 가는지 명확하지 않기 때문에 코드의 가독성이 떨어지고 유지보수가 어려워짐
Props를 사용하지 않은 경우
import React, { useState } from 'react';
const ParentComponent = () => {
const [data, setData] = useState('Hello');
return (
<div>
<ChildComponent />
</div>
);
};
const ChildComponent = () => {
const data = 'Hello'; // 데이터가 어디서 오는지 명확하지 않음
return <div>{data}</div>;
};
export default ParentComponent;
Props를 사용한 경우
import React, { useState } from 'react';
const ParentComponent = () => {
const [data, setData] = useState('Hello'); // 상태 정의
return (
<div>
/* ChildComponent에 props로 data를 전달 */
<ChildComponent data={data} />
</div>
);
};
// ChildComponent는 props로 data를 받음
const ChildComponent = ({ data }) => {
// 받은 props(data)를 렌더링
return <div>{data}</div>;
};
export default ParentComponent;
컴포넌트의 재사용성 감소
특정 데이터나 기능에 종속된 컴포넌트를 만들게 되고, 다른 상황에서 재사용 하기 어려워짐
Props를 사용하지 않은 경우
import React from 'react';
// 이 Button 컴포넌트는 고정된 텍스트 "Click Me"를 버튼 안에 표시
const Button = () => {
return <button>Click Me</button>;
};
export default Button;
// 이 상태에서는 다른 텍스트를 가진 버튼을 만들려면 컴포넌트를 수정하거나 새로운 컴포넌트를 만들어야 함
Props를 사용한 경우
import React from 'react';
// Button 컴포넌트는 label 이라는 props를 받음
const Button = ({ label }) => {
// 받은 label props를 버튼 안에 표시
return <button>{label}</button>;
};
export default Button;
// 이 Button 컴포넌트는 여러 곳에서 다양한 label로 재사용 가능
import React from 'react';
import Button from './Button';
const App = () => {
return (
<div>
{/* 서로 다른 label을 가진 Button 컴포넌트를 여러 번 사용 가능 */}
<Button label="Submit" />
<Button label="Cancel" />
<Button label="Click Me" />
</div>
);
};
export default App;
상태 관리의 복잡성
상태(state)는 컴포넌트 내부에서 관리되고, props는 외부에서 전달되는 데이터이다.
props를 사용하지 않으면 상태 관리가 복잡해지고, 상태 간의 의존성이 높아져 코드가 복잡해질 수 있다.
Props를 사용하지 않은 경우
import React, { useState } from 'react';
const ParentComponent = () => {
const [count, setCount] = useState(0); // 상태를 정의
return (
<div>
{/* ChildComponent에 상태(count)를 props로 전달하지 않음 */}
<ChildComponent />
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
const ChildComponent = () => {
const count = 0; // 상수로 설정된 값, 부모의 상태와 무관
return <div>Count: {count}</div>;
};
export default ParentComponent;
/*
`ParentComponent`는 `count` 라는 상태를 갖고 있지만, `ChildComponent`를 렌더링 할 때
이 상태를 `ChildComponent`에 props로 전달하지 않았다.
`ChildComponent`는 자신의 내부에서 상수로 `count` 값을 설정하고 있다.
그래서 `ParentComponent`의 상태 변화가 `ChildComponent`에 반영되지 않는다.
*/
Props를 사용한 경우
import React, { useState } from 'react';
const ParentComponent = () => {
const [count, setCount] = useState(0); // 상태를 정의
return (
<div>
{/* ChildComponent에 상태(count)를 props로 전달 */}
<ChildComponent count={count} />
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
// ChildComponent는 props로 count를 받음
const ChildComponent = ({ count }) => {
// 받은 props(count)를 렌더링
return <div>Count: {count}</div>;
};
export default ParentComponent;
/*
`ParentComponent`가 `ChildComponent`를 받아서 렌더링 할 때 `count` 상태를 props로 전달하고
`ChildComponent`는 이 props를 받아서 화면에 표시한다.
`ParentComponent`의 상태 변화가 `ChildComponent`에도 반영되어
상태 관리가 명확해지고 일관성이 생긴다.
*/
테스트의 어려움
props를 사용하지 않으면 외부 데이터에 의존하는 컴포넌트를 테스트 하는 것이 어려워질수 있다. 따라서 코드의 안정성을 떨어뜨릴 수 있다.
props를 사용하지 않은 경우
import React from 'react';
const Greeting = () => {
// 'World'라는 고정된 값을 사용
const name = 'World';
// 고정된 'World' 값을 사용하여 인사말을 표시
return <div>Hello, {name}!</div>;
};
export default Greeting;
// 컴포넌트가 고정된 값을 사용중이므로 다른 이름으로 인사말을 표시할 때마다 코드를 수정해야 함
props를 사용한 경우
import React from 'react';
// Greeting 컴포넌트는 props로 name을 받음
const Greeting = ({ name }) => {
// 받은 name props를 사용하여 인사말을 표시
return <div>Hello, {name}!</div>;
};
export default Greeting;
import React from 'react';
import Greeting from './Greeting';
const App = () => {
return (
<div>
<Greeting name="World" />
<Greeting name="Alice" />
<Greeting name="Bob" />
</div>
);
};
export default App;
코드의 일관성 부족
props를 사용하면 컴포넌트 간의 데이터 전달 방식이 일관성을 가지게 되지만, props를 사용하지 않으면 각 컴포넌트가 서로 다른 방식으로 데이터를 주고 받게 되어 코드 전체의 일관성이 떨어진다.
props를 사용하지 않은 경우
import React from 'react';
// Header 컴포넌트는 고정된 제목을 사용
const Header = () => {
const title = 'My App'; // 'My App'이라는 고정된 제목을 사용
return <h1>{title}</h1>; // 고정된 제목을 h1 요소로 렌더링
};
// Footer 컴포넌트는 고정된 푸터 텍스트를 사용
const Footer = () => {
const footerText = '© 2024 Namani'; // '© 2024 Namani'라는 고정된 텍스트를 사용
return <footer>{footerText}</footer>; // 고정된 텍스트를 footer 요소로 렌더링
};
// Header와 Footer 컴포넌트를 내보냄
export { Header, Footer };
props를 사용한 경우
import React from 'react';
// Header 컴포넌트는 props로 title을 받음
const Header = ({ title }) => {
return <h1>{title}</h1>; // 받은 title props를 h1 요소로 렌더링
};
// Footer 컴포넌트는 props로 footerText를 받음
const Footer = ({ footerText }) => {
return <footer>{footerText}</footer>; // 받은 footerText props를 footer 요소로 렌더링
};
// Header와 Footer 컴포넌트를 내보냄
export { Header, Footer };
import React from 'react';
import { Header, Footer } from './HeaderFooterComponents';
const App = () => {
return (
<div>
{/* 서로 다른 title과 footerText를 props로 전달 */}
<Header title="My App" />
<Footer footerText="© 2024 My Company" />
<Header title="Another App" />
<Footer footerText="© 2024 Another Company" />
</div>
);
};
export default App;
컴포넌트 추출
큰 컴포넌트에서 일부를 추출해서 새로운 컴포넌트를 만드는 것
컴포넌트는 기능 단위로 구분하는 것이 좋고, 나중에 곧바로 재사용이 가능한 형태로 추출하는 것이 좋다.
'TIL > React' 카테고리의 다른 글
[TIL/React] BrowserRouter, Navigation, Routes, Route (0) | 2024.07.30 |
---|---|
[TIL/React] Hooks, useState, useEffect (0) | 2024.07.24 |
[TIL/React] State, 생명주기 (0) | 2024.07.24 |
[TIL/React] 리액트 엘리먼트, DOM 엘리먼트 (0) | 2024.07.20 |
[TIL/React] 리액트 앱의 실행 순서와 컴포넌트 (0) | 2024.07.16 |