โœ…ย Component๋ž€?

๐ŸŒˆย ๊ฒฐ๋ก 

  • ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ •ํ™•ํ•˜๊ฒŒ ์ธ์ง€ํ•˜๊ณ  ์‚ฌ์šฉํ•ด์•ผ ํ•จ

โœ๏ธย ๋‚ด์šฉ

๊ณต์‹ ๋ฌธ์„œ์—์„œ Component ์˜๋ฏธ

  1. ์ปดํฌ๋„ŒํŠธ ์˜๋ฏธ(์˜›๋‚ )

    • ์Šค์Šค๋กœ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์บก์Šํ™”๋œ ์ปดํฌ๋„ŒํŠธ
    • ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ์กฐํ•ฉํ•ด ๋ณต์žกํ•œ UI๋ฅผ ๋งŒ๋“ฆ
    • ์ปดํฌ๋„ŒํŠธ ๋กœ์ง์€ ํ…œํ”Œ๋ฆฟ์ด ์•„๋‹Œ JS๋กœ ์ž‘์„ฑ๋จ
    • ๋”ฐ๋ผ์„œ ๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์•ฑ ์•ˆ์—์„œ ์†์‰ฝ๊ฒŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๊ณ , DOM๊ณผ ๋ณ„๊ฐœ๋กœ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌ ํ•  ์ˆ˜ ์žˆ์Œ
  2. ์ปดํฌ๋„ŒํŠธ ์˜๋ฏธ(New)

    • ๊ธฐ์กด์—๋Š”
    • ์›น ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค ๋•Œ ์›น ๊ฐœ๋ฐœ์ž๊ฐ€ ์ปจํ…์ธ ๋ฅผ ๋งˆํฌ์—…ํ•œ ๋‹ค์Œ JS๋ฅผ ๋ฟŒ๋ ค์„œ ์ƒํ˜ธ์ž‘์šฉ์„ ์ถ”๊ฐ€ ํ•จ. ์ด๋Š” ์›น์—์„œ ์ƒํ˜ธ์ž‘์šฉ์ด ์ค‘์š”ํ–ˆ๋˜ ์‹œ์ ˆ์— ํšจ๊ณผ์ ์ด์—ˆ์Œ
    • ์ด์ œ๋Š”
    • ๋งŽ์€ ์‚ฌ์ดํŠธ์™€ ๋ชจ๋“  ์•ฑ์—์„œ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ธฐ๋Œ€ํ•จ
    • React๋Š” ๋™์ผํ•œ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ๋„ ์ƒํ˜ธ์ž‘์šฉ์„ ์šฐ์„ ์‹œํ•จ
    • React ์ปดํฌ๋„ŒํŠธ๋Š” ๋งˆํฌ์—…์œผ๋กœ ๋ฟŒ๋ฆด ์ˆ˜ ์žˆ๋Š” JS ํ•จ์ˆ˜ ์ž„
    • ์ฐธ๊ณ 
    • https://react.dev/learn/thinking-in-react

Component๋ž€

  • ์‚ฌ์ „์  ์˜๋ฏธ: ๊ตฌ์„ฑํ•˜๋Š”, ๊ตฌ์„ฑํ•˜๊ณ  ์žˆ๋Š”, ์„ฑ๋ถ„์˜ / ๊ตฌ์„ฑ ์š”์†Œ, ์„ฑ๋ถ„

โญ๏ธ ์š”์•ฝ

  • ์ปดํฌ๋„ŒํŠธ ๋ž€

    • ๋งŽ์€ ์‚ฌ์ดํŠธ์™€ ๋ชจ๋“  ์•ฑ์—์„œ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ธฐ๋Œ€ํ•จ
    • React๋Š” ๋™์ผํ•œ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ๋„ ์ƒํ˜ธ์ž‘์šฉ์„ ์šฐ์„ ์‹œํ•จ
    • React ์ปดํฌ๋„ŒํŠธ๋Š” ๋งˆํฌ์—…์œผ๋กœ ๋ฟŒ๋ฆด ์ˆ˜ ์žˆ๋Š” JS ํ•จ์ˆ˜ ์ž„

โœ…ย Self Closing Tags

๐ŸŒˆย ๊ฒฐ๋ก 

  • Self Closing Tags๋ฅผ ์ •ํ™•ํžˆ ์ธ์ง€ํ•˜๊ณ  ์‚ฌ์šฉํ•˜์ž

โœ๏ธย ๋‚ด์šฉ

  1. Self Closing Tags ์˜๋ฏธ

    • ๋ช…์‹œ์ ์œผ๋กœ ๋‹ซ๋Š” ํƒœ๊ทธ๊ฐ€ ํ•„์š”๊ฐ€ ์—†์Œ
    • ๊ธฐ๋ณธ HTML ์š”์†Œ์ธ์ง€ ์•„๋‹Œ์ง€ ๋ช…ํ™•ํ•œ ์ฐจ์ด๋ฅผ ๊ฐ€์ ธ์•ผ ํ•จ
    • Vue์—์„œ๋Š” HTML์—์„œ ์‚ฌ์šฉ๋˜์–ด์ง€๋Š” header์™€ ๊ฐ™์€ ํƒœ๊ทธ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ•จ ๋Œ€์‹ ์— app-header ์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•จ
    function HelloWorld() {
     return (
       <Clean>
         <Code>
           <img />
           <br />
         </Code>
       </Clean>
     );
    }
  2. ์ฐธ๊ณ 

โญ๏ธ ์š”์•ฝ

  • Self Closing Tags๋ฅผ ์ •ํ™•ํžˆ ์ธ์ง€ํ•˜๊ณ  ์‚ฌ์šฉํ•˜์ž

โœ…ย Fragment ์ง€ํ–ฅํ•˜๊ธฐ

๐ŸŒˆย ๊ฒฐ๋ก 

  • Fragment๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ๊ณ  ์“ฐ์ž.

โœ๏ธย ๋‚ด์šฉ

โญ๏ธ ์š”์•ฝ

  • 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>
  );
}

โœ๏ธย ๋‚ด์šฉ

  • ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์ปดํฌ๋„ŒํŠธ ์„ ์–ธ์‹œ ๋ฌธ์ œ์ 

    1. ๊ฒฐํ•ฉ๋„๊ฐ€ ์ฆ๊ฐ€ํ•จ
    2. ๊ตฌ์กฐ์ ์œผ๋กœ ์Šค์ฝ”ํ”„์ ์œผ๋กœ ์ข…์†๋œ ๊ฐœ๋ฐœ์ด ๋จ
    3. ๋‚˜์ค‘์— ํ™•์žฅ์„ฑ์ด ์ƒ๊ฒจ์„œ ๋ถ„๋ฆฌ๋  ๋•Œ ๊ต‰์žฅํžˆ ํž˜๋“ฆ
    4. ์„ฑ๋Šฅ ์ €ํ•˜
    5. ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋” ์ผ์–ด๋‚˜๋ฉด โ‡’ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ ์žฌ ์ƒ์„ฑ

โญ๏ธ ์š”์•ฝ

  • ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ ์–ธํ•˜๋ฉด ๊ฒฐํ•ฉ๋„๊ฐ€ ์ฆ๊ฐ€ํ•˜๊ณ  ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ๋‹ค.

โœ…ย 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;

โญ๏ธ ์š”์•ฝ

  • ๊ฐœ๋ฐœ์„ ํ•  ๋•Œ ๊ทœ์น™์„ ๊ฐ€์ง€๊ณ  ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•˜์ž.

์ฐธ๊ณ