โ ย Component๋?
๐ย ๊ฒฐ๋ก
- ์ปดํฌ๋ํธ๊ฐ ๋ฌด์์ธ์ง ์ ํํ๊ฒ ์ธ์งํ๊ณ ์ฌ์ฉํด์ผ ํจ
โ๏ธย ๋ด์ฉ
๊ณต์ ๋ฌธ์์์ Component ์๋ฏธ
-
์ปดํฌ๋ํธ ์๋ฏธ(์๋ )
- ์ค์ค๋ก ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ์บก์ํ๋ ์ปดํฌ๋ํธ
- ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ์กฐํฉํด ๋ณต์กํ UI๋ฅผ ๋ง๋ฆ
- ์ปดํฌ๋ํธ ๋ก์ง์ ํ ํ๋ฆฟ์ด ์๋ JS๋ก ์์ฑ๋จ
- ๋ฐ๋ผ์ ๋ค์ํ ํ์์ ๋ฐ์ดํฐ๋ฅผ ์ฑ ์์์ ์์ฝ๊ฒ ์ ๋ฌํ ์ ์๊ณ , DOM๊ณผ ๋ณ๊ฐ๋ก ์ํ๋ฅผ ๊ด๋ฆฌ ํ ์ ์์
-
์ปดํฌ๋ํธ ์๋ฏธ(New)
- ๊ธฐ์กด์๋
- ์น ํ์ด์ง๋ฅผ ๋ง๋ค ๋ ์น ๊ฐ๋ฐ์๊ฐ ์ปจํ ์ธ ๋ฅผ ๋งํฌ์ ํ ๋ค์ JS๋ฅผ ๋ฟ๋ ค์ ์ํธ์์ฉ์ ์ถ๊ฐ ํจ. ์ด๋ ์น์์ ์ํธ์์ฉ์ด ์ค์ํ๋ ์์ ์ ํจ๊ณผ์ ์ด์์
- ์ด์ ๋
- ๋ง์ ์ฌ์ดํธ์ ๋ชจ๋ ์ฑ์์ ์ํธ์์ฉ์ ๊ธฐ๋ํจ
- React๋ ๋์ผํ ๊ธฐ์ ์ ์ฌ์ฉํ๋ฉด์๋ ์ํธ์์ฉ์ ์ฐ์ ์ํจ
- React ์ปดํฌ๋ํธ๋ ๋งํฌ์ ์ผ๋ก ๋ฟ๋ฆด ์ ์๋ JS ํจ์ ์
- ์ฐธ๊ณ
- https://react.dev/learn/thinking-in-react
Component๋
- ์ฌ์ ์ ์๋ฏธ: ๊ตฌ์ฑํ๋, ๊ตฌ์ฑํ๊ณ ์๋, ์ฑ๋ถ์ / ๊ตฌ์ฑ ์์, ์ฑ๋ถ
โญ๏ธ ์์ฝ
-
์ปดํฌ๋ํธ ๋
- ๋ง์ ์ฌ์ดํธ์ ๋ชจ๋ ์ฑ์์ ์ํธ์์ฉ์ ๊ธฐ๋ํจ
- React๋ ๋์ผํ ๊ธฐ์ ์ ์ฌ์ฉํ๋ฉด์๋ ์ํธ์์ฉ์ ์ฐ์ ์ํจ
- React ์ปดํฌ๋ํธ๋ ๋งํฌ์ ์ผ๋ก ๋ฟ๋ฆด ์ ์๋ JS ํจ์ ์
โ ย Self Closing Tags
๐ย ๊ฒฐ๋ก
Self Closing Tags
๋ฅผ ์ ํํ ์ธ์งํ๊ณ ์ฌ์ฉํ์
โ๏ธย ๋ด์ฉ
-
Self Closing Tags
์๋ฏธ- ๋ช ์์ ์ผ๋ก ๋ซ๋ ํ๊ทธ๊ฐ ํ์๊ฐ ์์
- ๊ธฐ๋ณธ HTML ์์์ธ์ง ์๋์ง ๋ช ํํ ์ฐจ์ด๋ฅผ ๊ฐ์ ธ์ผ ํจ
Vue
์์๋ HTML์์ ์ฌ์ฉ๋์ด์ง๋ header์ ๊ฐ์ ํ๊ทธ ์ฌ์ฉ์ด ๋ถ๊ฐํจ ๋์ ์app-header
์ด๋ฐ์์ผ๋ก ์ฌ์ฉํด์ผ ํจ
function HelloWorld() { return ( <Clean> <Code> <img /> <br /> </Code> </Clean> ); }
- ์ฐธ๊ณ
โญ๏ธ ์์ฝ
Self Closing Tags
๋ฅผ ์ ํํ ์ธ์งํ๊ณ ์ฌ์ฉํ์
โ ย Fragment ์งํฅํ๊ธฐ
๐ย ๊ฒฐ๋ก
- Fragment๊ฐ ๋ฌด์์ธ์ง ์๊ณ ์ฐ์.
โ๏ธย ๋ด์ฉ
-
React v16.2 ์ถ์
- Fragment ๋ฐํ์์ Fragment๋ ์ฌ๋ผ์ง
- Babel ๋ฒ์ ผ์ ๋ฐ๋ผ์ Fragment Short Cut ์ฌ์ฉ ์ฌ๋ถ๋ ํ์ธํด์ผ ๋จ
-
index๋ฅผ ์ฃผ์ ํ ๋, Short Cut์ด ์๋ Fragment ์ปดํฌ๋ํธ ์ฌ์ฉํด์ผ ํจ
function Example() { return ( <> <Child /> </> ); }
-
์ฐธ๊ณ
โญ๏ธ ์์ฝ
- Fragment๊ฐ ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ์.
โ ย Fragment ์ง์ํ๊ธฐ
๐ย ๊ฒฐ๋ก
- ์ํฉ์ ๋ฐ๋ผ ๋ถํ์ํ Fragment๋ฅผ ์ค์ด์.
โ๏ธย ๋ด์ฉ
- ๋ถํ์ํ Fragment ์ฌ์ฉ์ ์ค์ด์.
// ๋ถํ์ํ ๊ณ์ธต ์ค์ด๊ธฐ
function Example() {
return (
<>
<div>
<div></div>
</div>
</>
);
}
function StringRender() {
// return <>'Clean Code'</> โ
return 'Clean Code';
}
// ๋ ๋๋ง ๋ ํ์ ์๋ JSX ์ค์ด๊ธฐ
function ConditionalRenderingEX() {
return(
<div>
<h1>{isLoggedIn ? 'User' : <></>}</h1>
<h1>{isLoggedIn ? 'User' : null}</h1>
<h1>{isLoggedIn && 'User'}</h1>
{isLoggedIn && <h1>User</h1>
</dvi>
)
}
โญ๏ธ ์์ฝ
- ๋ถํ์ํ Fragment ์ฌ์ฉ์ ์ค์ด์.
โ ย ์์๋๋ฉด ์ข์ ์ปดํฌ๋ํธ ๋ค์ด๋ฐ
๐ย ๊ฒฐ๋ก
function ComponentNaming() {
return (
<>
<h1></h1> // ๐ค lowercase
<h2></h2>
<div></div>
<input />
<MyuComponent></MyComponent> // ๐ค pascal case
<my-component></my-component> // ๐ค kebab case
</>
)
}
โ๏ธย ๋ด์ฉ
์ปดํฌ๋ํธ ๋ค์ด๋ฐ
- ์ผ๋ฐ์ ์ผ๋ก ์ปดํฌ๋ํธ PascalCase
- ๊ธฐ๋ณธ HTML ์์๋ lower case
-
route based file name
component-naming.jsx
โ<ComponentNaming />
component-naming/index.jsx
โ<ComponentNaming />
โญ๏ธ ์์ฝ
- ์ปดํฌ๋ํธ ๋ค์ด๋ฐ ๊ท์น์ ์ดํดํ๊ณ ์ฌ์ฉํ์
โ ย JSX ์ปดํฌ๋ํธ ํจ์๋ก ๋ฐํ
๐ย ๊ฒฐ๋ก
// ๐ค ์ด๋ค ํํ๊ฐ ๋ง์๊น?
return (
<div>
{TopRender()}
<TopRender />
{renderMain()}
</div>
);
โ๏ธย ๋ด์ฉ
-
JSX ์ปดํฌ๋ํธ ํจ์๋ก ๋ฐํ์ ๋ฌธ์ ์
- ์ค์ฝํ๊ฐ ๊ผฌ์
- ์ธ์ ์ด๋ป๊ฒ ์ฐ์ผ์ง ๋ชฐ๋ผ์ ์ํ
- ์ปดํ์ผ ๊ณผ์ ์์ ์บ์น ๋ชปํ๋ฉด ์น๋ช ์ ์ธ ์ค๋ฅ ๋ฐ์
- ๋ฆฌํด ๊ฐ์ด ๋ฌด์์ธ์ง ํ์ ํ๊ธฐ ์ด๋ ค์
- props ๋ฃ๊ธฐ๊ฐ ํ๋ฆ
function ReturnJSXFunction() {
const TopRender = () => {
return (
<header>
<h1>Clean Code JS</h1>
</header>
);
};
const renderMain = () => {
return (
<main>
<p>Clean Code</p>
</main>
);
};
return (
<div>
{TopRender()}
{renderMain()}
</div>
);
}
โญ๏ธ ์์ฝ
-
ํจ์๋ก return ํ๋ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ๋จ์ ์ด ๋ฐ์
- scope๋ฅผ ์์๋ณด๊ธฐ ์ด๋ ค์
- ๋ฐํ ๊ฐ์ ๋ฐ๋ก ์๊ธฐ ์ด๋ ค์
- props ์ ๋ฌ ๋ฑ ์ผ๋ฐ์ ์ธ ํจํด์ด ์๋
โ ย ์ปดํฌ๋ํธ ๋ด๋ถ์ ์ปดํฌ๋ํธ ์ ์ธ
๐ย ๊ฒฐ๋ก
// โ
function OuterComponent() {
const InnerComponent = () => {
return <div>Inner component</div>;
};
return (
<div>
<InnerComponent />
</div>
);
}
// โ
const InnerComponent = () => {
return <div>Inner component</div>;
};
function OuterComponent() {
return (
<div>
<InnerComponent />
</div>
);
}
โ๏ธย ๋ด์ฉ
-
์ปดํฌ๋ํธ ๋ด๋ถ์ ์ปดํฌ๋ํธ ์ ์ธ์ ๋ฌธ์ ์
- ๊ฒฐํฉ๋๊ฐ ์ฆ๊ฐํจ
- ๊ตฌ์กฐ์ ์ผ๋ก ์ค์ฝํ์ ์ผ๋ก ์ข ์๋ ๊ฐ๋ฐ์ด ๋จ
- ๋์ค์ ํ์ฅ์ฑ์ด ์๊ฒจ์ ๋ถ๋ฆฌ๋ ๋ ๊ต์ฅํ ํ๋ฆ
- ์ฑ๋ฅ ์ ํ
- ์์ ์ปดํฌ๋ํธ ๋ฆฌ๋ ๋ ์ผ์ด๋๋ฉด โ ํ์ ์ปดํฌ๋ํธ ์ฌ ์์ฑ
โญ๏ธ ์์ฝ
- ์ปดํฌ๋ํธ ๋ด๋ถ์ ์ปดํฌ๋ํธ๋ฅผ ์ ์ธํ๋ฉด ๊ฒฐํฉ๋๊ฐ ์ฆ๊ฐํ๊ณ ์ฑ๋ฅ์ด ์ ํ๋ ์ ์๋ค.
โ ย DisplayName
๐ย ๊ฒฐ๋ก
- ํ์ฅ์ฑ์ด ๋์ ์ปดํฌ๋ํธ๋ฅผ ๋๋ฒ๊น
ํ๊ธฐ ์ํด
displayName
์ ์ ํ์ฉํ์
โ๏ธย ๋ด์ฉ
DisplayName
- ๋๋ฒ๊น ํ๋๋ฐ ์ข์ ์์
// Case 1
const InputText = forwardRef((props, ref)) => {
return <input type="text" ref={ref} />;
});
InputText.displayName = 'InputText' // ๋ง์ฝ ๐ค displayName์ ์์ฑ ์ํ๋ค๋ฉด?
// Case 2
const withRouter = (Component) => {
const WithRouter = (props) => {
const location = useLocation();
const navigate = useNavigate();
const params = useParams();
const navigationType = useNavigationType();
return (
<Component
{...props}
location={location}
navigate={navigate}
params={params}
navigationType={navigationType}
/>
);
};
WithRouter.displayName = Component.displayName ?? Component.name ?? 'WithRouterComponent'
return WithRouter
};
โญ๏ธ ์์ฝ
- React ๊ฐ๋ฐ์ ๋๋ฒ๊น ์ ์ํด displayName์ ์ ํ์ฉํ์.
โ ย Component ๊ตฌ์ฑํ๊ธฐ
๐ย ๊ฒฐ๋ก
- ๊ฐ๋ฐ์ ํ ๋, ์ด๋ค ์์ ๋ฐ ํ๋ฆ์ผ๋ก ๊ฐ๋ฐ์ ์งํํด์ผ ํจ
โ๏ธย ๋ด์ฉ
// โ
๋ณํ์ง ์์ ๊ฐ์ ์ปดํฌ๋ํธ ์ธ๋ถ๋ก ๋นผ๊ธฐ
const DEFAULT_COUNT = 100;
const DEFAULT_DELAY = 500;
// โ
ํ์
๋๋ ์ธํฐํ์ด์ค๋ ์ปดํฌ๋ํธ ๋ฐ์ผ๋ก ๋นผ๊ธฐ
interface SomeComponentProps {
}
// โ
์ปดํฌ๋ํธ์ ๊ด๋ จ์๋ ๋ก์ง์ ์ปดํฌ๋ํธ ์ธ๋ถ๋ก ๋นผ๊ธฐ
const handleClose = () => {
// Date
// Local Storage
}
const SomeComponent = ({ prop1, prop2 }: SomeComponentProps) => {
// โ
flag ๋๋ ref๋ ์๋จ์ ํ์
let isHold = false;
const ref = useRef(null);
// โ
React Third-Party ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ
์ ์ฌ์ฉ์ ์๋จ์ ํ์
const location = useLocation();
const queryClient = useQueryClient();
const state = useSelector((state) => state);
// โ
๋ด๊ฐ ๋ง๋ Hooks์ ์๋จ์ ํ์
const state = useCustomHooks((state) => state);
// โ
์ปดํฌ๋ํธ ๋ด๋ถ ์ํ๋ฅผ ์๋จ์ ํ์
const [state, setState] = useState('someState");
const onClose = () => handleClose();
// Early Return JSX
if (isHold) {
return <div>๋ฐ์ดํฐ๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค.</div>
}
// โ
Main JSX์ ๊ฐ์ฅ ๊ฐ๊น์ด ๊ณณ์ ์์น
// - ์ต์ 1๊ฐ๋ก ์ฌ์ฉํ ์ ์๋๋ก ์งํ
useEffect(() => {
}, []);
// โ
JSX ๋ฐํ์ ํญ์ ์ฌ์ ์ ๊ฐํ์ ๋๋ฐ
return (
<div className="tooltip">
<div className="msg">Hello World</div>
<button
className="close"
type="button"
onClick={onClose}
/>
</div>
)
}
// โ
์ปดํฌ๋ํธ ์ธ๋ถ๋ก ๋นผ๊ธฐ(์ปดํฌ๋ํธ ํ๋จ)
// - ์ฝ๋๊ฐ ๋ง์ ๊ฒฝ์ฐ, ํ์ผ๋ก ๋นผ๊ธฐ
const Button = styled.a<{ $primary?: boolean; }>`
padding: 0.5rem 0;
transition: all 200ms ease-in-out;
width: 11rem;
&:hover {
filter: brightness(0.85);
}
`
export default SomeComponent;
โญ๏ธ ์์ฝ
- ๊ฐ๋ฐ์ ํ ๋ ๊ท์น์ ๊ฐ์ง๊ณ ๊ฐ๋ฐ์ ์งํํ์.
์ฐธ๊ณ
- ๐ย ๊ฒฐ๋ก
- โ๏ธย ๋ด์ฉ
- ๊ณต์ ๋ฌธ์์์ Component ์๋ฏธ
- Component๋
- โญ๏ธ ์์ฝ
- ๐ย ๊ฒฐ๋ก
- โ๏ธย ๋ด์ฉ
- โญ๏ธ ์์ฝ
- ๐ย ๊ฒฐ๋ก
- โ๏ธย ๋ด์ฉ
- โญ๏ธ ์์ฝ
- ๐ย ๊ฒฐ๋ก
- โ๏ธย ๋ด์ฉ
- โญ๏ธ ์์ฝ
- ๐ย ๊ฒฐ๋ก
- โ๏ธย ๋ด์ฉ
- ์ปดํฌ๋ํธ ๋ค์ด๋ฐ
- โญ๏ธ ์์ฝ
- ๐ย ๊ฒฐ๋ก
- โ๏ธย ๋ด์ฉ
- โญ๏ธ ์์ฝ
- ๐ย ๊ฒฐ๋ก
- โ๏ธย ๋ด์ฉ
- โญ๏ธ ์์ฝ
- ๐ย ๊ฒฐ๋ก
- โ๏ธย ๋ด์ฉ
- DisplayName
- โญ๏ธ ์์ฝ
- ๐ย ๊ฒฐ๋ก
- โ๏ธย ๋ด์ฉ
- โญ๏ธ ์์ฝ
- ์ฐธ๊ณ