Untitled

๐Ÿ˜‰ ํ—ท๊ฐˆ๋ ธ๋˜ & ๋ชฐ๋ž๋˜ ๋ถ€๋ถ„๋“ค๋งŒ ์ •๋ฆฌํ•˜๋Š” ๋‚˜๋งŒ์˜ TIL
๐Ÿ˜ฏ ๋ชจ๋“  ๊ฐ•์˜ ๋‚ด์šฉ์€ ์ ์ง€ ์•Š์•„์š”!

์˜ค๋Š˜์˜ ์†Œ๊ฐ์€?
์ด์ œ ์ข€ ์นœํ•ด์ง€๋‚˜ ์‹ถ์—ˆ์ง€๋งŒ ๋ทฐ๋Š” ๋– ๋‚˜๊ฐ”์Šต๋‹ˆ๋‹ค... ํ‘ํ‘

๊ธฐ๋‹ค๋ฆฌ๊ณ  ๊ธฐ๋‹ค๋ฆฌ๋˜ ๋ฆฌ์—‘ํŠธ ์‹œ์ž‘์ž…๋‹ˆ๋‹ค!
์ฒ˜์Œ์— ์‹ค์Šต์„ ์‹œ์ž‘ํ•˜๊ณ  ๊ตฌ์กฐ๊ฐ€ ํ•œ ๋ˆˆ์— ์žกํžˆ์ง€ ์•Š์•„ ํž˜๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ํƒ€์ดํ•‘์„ ํ•˜๋‹ค๋ณด๋‹ˆ.. ๋น„์Šทํ•˜๋„ค์š”?!

๊ผญ ์ž˜ ํ•™์Šตํ•ด์„œ ํ”„๋กœ์ ํŠธ์— ๋…น์—ฌ๋‚ด๊ฒ ์Šต๋‹ˆ๋‹ค.




[1] React

React๋Š” facebook์—์„œ ๋‚˜์˜จ ํ”„๋ก ํŠธ์—”๋“œ(์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.


[1-1] ํŠน์ง•

  • Reactive Programming

React๋Š” Reactive Programming์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰ ์ƒํƒœ๋ฅผ ๊ด€์ฐฐํ•˜๊ณ  ๋ณ€ํ™”๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ, ์—ฐ๊ด€๋œ ๊ณณ์—์„œ ๋‹ค์‹œ ์—ฐ์‚ฐ์ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.


  • View

๋˜ํ•œ React๋Š” MVC ์•„ํ‚คํ…์ณ ํŒจํ„ด ์ค‘ View๋งŒ์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ ์ปดํฌ๋„ŒํŠธ์˜ ์กฐํ•ฉ์œผ๋กœ View๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.


  • Virtual DOM

Virtual DOM์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ํ•œ ๋ฒˆ์— ๋ Œ๋”๋งํ•˜๋ฏ€๋กœ, ๋ณ„๋‹ค๋ฅธ ์ตœ์ ํ™” ์—†์ด ๋น ๋ฅธ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ DOM์„ ์ง์ ‘ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ ๋ณด๋‹ค๋Š” ๋Š๋ฆฝ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์„ฑ๋Šฅ๋ณด๋‹ค๋Š” ๊ฐœ๋ฐœ ํŽธ์˜์„ฑ์„ ์œ„ํ•ด Virtual DOM์„ ์ฑ„ํƒํ–ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.




[2] ๋ฆฌ์—‘ํŠธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜

create-react-app์„ ์‚ฌ์šฉํ•˜์—ฌ react-app์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

npx create-react-app my-app
npm start

Untitled 1

Untitled 2


[2-1] ํ‘œํ˜„์‹

ํ‘œํ˜„์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function App() {
  const name = "์ง€์˜";

  return (
    // ์ด์™€ ๊ฐ™์ด Javascript ํŒŒ์ผ ๋‚ด์—์„œ html ๊ฐ€์ƒ ๋”์„ ํฌํ•จํ•˜๋Š” ํ˜•ํƒœ๋ฅผ JSX๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
    // javascript ๋‚ด์—์„œ class๊ฐ€ ์˜ˆ์•ฝ์–ด๊ธฐ ๋•Œ๋ฌธ์— className์„ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค.
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React with {name} // ์ด๋ ‡๊ฒŒ ํ‘œํ˜„์‹์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
        </a>
      </header>
    </div>
  );
}


[2-2] ์กฐ๊ฑด๋ฌธ

์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์—๋„ ํ•ด๋‹น ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์ฃผ๋กœ ์‚ผํ–ฅ ์—ฐ์‚ฐ์ž๋„ ๋งŽ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

// ํ‘œํ˜„์‹ ์‚ฌ์šฉ
{
  showLink && (
    <a
      className="App-link"
      href="https://reactjs.org"
      target="_blank"
      rel="noopener noreferrer"
    >
      Learn React with {name}
    </a>
  );
}
// showLink๊ฐ€ true์ผ๋•Œ๋งŒ ํ•ด๋‹น a ํƒœ๊ทธ๊ฐ€ ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค.
// ์‚ผํ–ฅ ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ
{
  showLogo === "show" ? (
    <img src={logo} className="App-logo" alt="logo" />
  ) : (
    <h1>์˜ค์ž‰</h1>
  );
}


[2-3] ๋ฐ˜๋ณต๋ฌธ

๋ฐ˜๋ณตํ•ด์„œ ๋ Œ๋”๋ง์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” mapํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰ VanillaJS์˜ ๋ฐ˜๋ณต ๋ Œ๋”๋ง ๊ตฌ๋ฌธ์„ ํ‘œํ˜„์‹ ์•ˆ์—์„œ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<ul>
  {names.map((item) => {
    return <li key={item}>{item}</li>;
    // ๋ฐ˜๋ณต๋ฌธ์—์„œ๋Š” ๋ฐ˜๋“œ์‹œ key๋ฅผ ์ ์–ด์ค๋‹ˆ๋‹ค.
    // react์˜ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.
  })}
</ul>




[3] ์ปดํฌ๋„ŒํŠธ๋ž€?

๋ฆฌ์—‘ํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” ์—ฌ๋Ÿฌ ๋กœ์ง์„ ๋‹ด์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ƒํƒœ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ๋Š” ํŠธ๋ฆฌ ๊ตฌ์กฐ๋กœ ์„œ๋กœ ๋ฐ์ดํ„ฐ์™€ ๋ฉ”์„ธ์ง€๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ, ๋ฐ์ดํ„ฐ๋Š” ์ƒ์œ„์—์„œ ํ•˜์œ„๋กœ (๋‹จ๋ฐฉํ–ฅ)์œผ๋กœ ํ๋ฆ…๋‹ˆ๋‹ค.


์ปดํฌ๋„ŒํŠธ๋Š” ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•œ ํ˜•ํƒœ๋กœ ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” UI๋ฅผ ์ถ”์ƒ์ ์œผ๋กœ ๋ฐ”๋ผ๋ณด๋Š” ๊ด€์ ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.


๋˜ํ•œ ๋ฆฌ์—‘ํŠธ์˜ ์ปดํฌ๋„ŒํŠธ๋Š” ํ•จ์ˆ˜๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ๋Š” Props๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„์„œ ํ•จ์ˆ˜ ๋‚ด์˜ ๋กœ์ง์„ ๊ฑฐ์ณ JSX๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.


[3-1] ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ

์ปดํฌ๋„ŒํŠธ๋Š” ์ฃผ๋กœ src/components ์•ˆ์— ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

Untitled 3

์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฆ„์œผ๋กœ ํด๋”๋ฅผ ์ƒ์„ฑํ•˜๊ณ , index.js๋กœ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.


// Logo Component (index.js)
import logo from "./logo.svg";
import propTypes from "prop-types"; // props์˜ ํƒ€์ž…์„ ์ง€์ •ํ•ด์ค๋‹ˆ๋‹ค.

function Logo({ size = 200 }) {
  return (
    <img
      src={logo}
      className="App-logo"
      alt="logo"
      style={{ width: size, height: size }}
    />
  );
}

Logo.propTypes = {
  size: propTypes.number,
};

export default Logo;

// App.js
import "./App.css";
import Logo from "./components/Logo";

function App() {
  return (
    // ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฆ„์œผ๋กœ ํƒœ๊ทธ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    <div className="App">
      <header className="App-header">
        <Logo size={100} />
        <Logo />
		// ...
	);
}




[4] ๋ถ„๊ธฐ์™€ ๋ฐ˜๋ณต

์ปดํฌ๋„ŒํŠธ๋Š” ์œ„์—์„œ ์‚ดํŽด๋ดค๋“ฏ์ด JSX๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” โ€˜ํ•จ์ˆ˜โ€™์ž…๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ ๋‚ด์—์„œ JSX๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณผ์ •์—์„œ ๋ถ„๊ธฐ์™€ ๋ฐ˜๋ณต์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


JSX ๋‚ด์—์„œ if์™€ for์™€ ๊ฐ™์€ ๋ฌธ๋ฒ• ์‚ฌ์šฉ์ด ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์—

ํŽธ์˜๋ฅผ ์œ„ํ•ด ์‚ผํ–ฅ์—ฐ์‚ฐ์ž, ๋…ผ๋ฆฌ๊ณฑ ์—ฐ์‚ฐ์ž์™€ map, filter์™€ ๊ฐ™์€ ๊ณ ์ฐจ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค.




[5] ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ

[5-2] ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ

์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉํ•  ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ , ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// Counter Component ์ผ๋ถ€
const [count, setCount] = useState(0);

const handleIncrease = () => {
  setCount(count + 1);
  if (onIncrease) {
    onIncrease(count + 1);
  }
};

const handleDecrease = () => {
  setCount(count - 1);
  if (onDecrease) {
    onDecrease(count - 1);
  }
};

return (
  <div>
    <span>{count}</span>
    <br />
    <button onClick={handleIncrease}>+</button>
    <button onClick={handleDecrease}>-</button>
  </div>
);


[5-3] ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ ๋ฉ”์„ธ์ง€ ์ „๋‹ฌ

props๋ฅผ ํ†ตํ•ด์„œ ๋ฉ”์„ธ์ง€๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•ด์„œ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ, ๊ฐ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋“ค์˜ ์ƒํƒœ์™€ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ๋Š” ์„œ๋กœ ๊ฐ„์„ญํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

// App Component ์ผ๋ถ€
<Counter
  onIncrease={(count) => {
    setTotalCount(totalCount + 1);
  }}
  onDecrease={(count) => {
    setTotalCount(totalCount - 1);
  }}
/>

์ด ๋ฐฉ๋ฒ• ์™ธ์—๋„ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”ํ›„์— ์ •๋ฆฌํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!




[6] ํ›…

[6-1] useState ํ›…

์ปดํฌ๋„ŒํŠธ์˜ ์ง€์—ญ ์ƒํƒœ ๊ด€๋ฆฌ์—๋Š” useState๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

useState๋Š” ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋‹ค์‹œ ๋ Œ๋”๋ง์„ ํ•ฉ๋‹ˆ๋‹ค.


React์—์„œ ์ƒํƒœ๋ž€ ๋™์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค.


useState๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒํƒœ์˜ ๊ธฐ๋ณธ๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„ฃ์–ด ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์ค๋‹ˆ๋‹ค.

ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์ฒซ๋ฒˆ์งธ ์›์†Œ๊ฐ€ ํ˜„์žฌ ์ƒํƒœ, ๋‘๋ฒˆ์งธ ์›์†Œ๊ฐ€ Setter ํ•จ์ˆ˜์ธ ๋ฐฐ์—ด์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

import { useState } from "react"; // ๋ฆฌ์—‘ํŠธ ํŒจํ‚ค์ง€์—์„œ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
import "./App.css";

function App() {
  const [visible, setVisible] = useState(false);
// ๋ฐฐ์—ด ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น์„ ํ†ตํ•ด ํ•ด๋‹น ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
<button onClick={() => setVisible(!visible)}>Toggle</button>

setVisible(Setter) ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฒซ๋ฒˆ์งธ ์›์†Œ์ธ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


[6-2] useEffect ํ›…

useEffect ํ›…์€ ๋ฌด์–ธ๊ฐ€ ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ ๊ฐ์ง€ํ•˜์—ฌ ๋ฐ˜์‘ํ•˜๋Š” ํ›…์ž…๋‹ˆ๋‹ค.

useEffect(() => {
  console.log("Change totalCount!");
}, [totalCount]);
// totalCount์˜ ๊ฐ’์ด ๋ณ€ํ•  ๋•Œ ๋งˆ๋‹ค ์•ˆ์˜ ๋กœ์ง์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค!

Untitled 4


๋งŒ์•ฝ ๋’ค์˜ ๋ฐฐ์—ด์— ์•„๋ฌด ๊ฐ’๋„ ๋„ฃ์ง€ ์•Š์•˜์„ ๋•, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ์œผ๋กœ ๋กœ๋“œ๋  ๋•Œ๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ๋Š” ์Šคํฌ๋กค ์ด๋ฒคํŠธ์™€ ๊ฐ™์ด ์ „์—ญ์ ์œผ๋กœ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•ด์•ผ ํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

useEffect(() => {
  const handleScroll = () => {
    console.log(window.scrollY);
  };

  document.addEventListener("scroll", handleScroll);
  return () => document.removeEventListener("scroll", handleScroll);
}, []);

Untitled 5


์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์€, ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ๋ผ์ ธ๋„ ์ด๋ฒคํŠธ๊ฐ€ ๋‚จ์•„์žˆ์ง€ ์•Š๊ฒŒ
return ๋ฌธ์— ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์คŒ์œผ๋กœ์จ ๊ผญ ์ด๋ฒคํŠธ๋ฅผ ์‚ญ์ œ
ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.


[6-3] useRef ํ›…

useRef๋Š” DOM์— ์ง์ ‘ ์ ‘๊ทผํ•  ๋•Œ์™€ ์ง€์—ญ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•  ๋•Œ ๋‘ ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

useRef๋Š” ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋”๋ผ๋„ ๋‹ค์‹œ ๋ Œ๋”๋ง์„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.


[1] DOM ์ ‘๊ทผ

const inputRef = useRef();

<input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Focus</button>
// ํ•ด๋‹น ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด useRef๋กœ ์ ‘๊ทผํ•œ input Dom ์š”์†Œ์˜ ํฌ์ปค์Šค๊ฐ€ ์žกํžˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Untitled 6


ํŠน์ • Component์˜ DOM์—๋„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ forwardRef๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

// Input Component
import React from "react";

const Input = React.forwardRef((_, ref) => {
  return (
    <>
      Input: <input ref={ref} />
    </>
  );
});

export default Input;
// App Component ์ผ๋ถ€
<Input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Focus</button>


[2] ์ง€์—ญ๋ณ€์ˆ˜

๋‹ค์‹œ ๋ Œ๋”๋งํ•˜์ง€ ์•Š์„ ์ง€์—ญ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// AutoCounter Component ์ผ๋ถ€
const [count, setCount] = useState(0);
const intervalId = useRef();

const handeleStart = () => {
  intervalId.current = setInterval(() => {
    setCount((count) => count + 1);
  }, 1000);
};

const handleStop = () => {
  clearInterval(intervalId.current);
};




[7] ํŽ˜์ด์ง€๋„ค์ด์…˜

๋ณดํ†ต ์„œ๋ฒ„ ์ธก์—์„œ ํŽ˜์ด์ง€๋ฅผ ๋ถ„ํ• ํ•ด์„œ ๋ณด๋‚ด์ฃผ๊ณค ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์ ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.


// Pagenation Component ์ผ๋ถ€
// defaultPage (๋งจ ์ฒ˜์Œ ์„ ํƒ๋  ํŽ˜์ด์ง€)
// limit (ํ•œ ํŽ˜์ด์ง€ ๋‹น ๋ณด์—ฌ์ค„ article์˜ ๊ฐฏ์ˆ˜)
// total (์ „์ฒด article์˜ ๊ฐฏ์ˆ˜)
// onChange (ํ•˜์œ„ -> ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ํŽ˜์ด์ง€๊ฐ€ ๋ฐ”๋€œ์„ ์•Œ๋ ค์ฃผ๋Š” ํ•จ์ˆ˜)
const Pagination = ({ defaultPage, limit, total, onChange }) => {
  const [page, setPage] = useState(defaultPage);
  const totalPage = Math.ceil(total / limit);

  const handleChangePage = (newPage) => {
    onChange(newPage);
    setPage(newPage);
  };

  return (
    <div>
      <button onClick={() => page !== 0 && handleChangePage(page - 1)}>
        ์ด์ „
      </button>
      {Array.from(new Array(totalPage), (_, i) => i)
        .filter((i) => {
          if (page < 3) {
            return i < 5;
          } else if (page > totalPage - 3) {
            return i >= totalPage - 5;
          }
          return i >= page - 2 && i <= page + 2;
        })
        .map((i) => (
          <button
            key={i}
            onClick={() => handleChangePage(i)}
            style={{ backgroundColor: page === i ? "aqua" : undefined }}
          >
            {i + 1}
          </button>
        ))}
      <button
        onClick={() => page + 1 !== totalPage && handleChangePage(page + 1)}
      >
        ๋‹ค์Œ
      </button>
    </div>
  );
};

VanillaJS์™€ ๋กœ์ง์ด ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ฒ๋จน์ง€ ๋ง๊ณ  ๊ณต๋ถ€ํ•ด๋ด์•ผ๊ฒ ์–ด์š”..!





์ถœ์ฒ˜

ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค

React.js Document

์นดํ…Œ๊ณ ๋ฆฌ: ,

์—…๋ฐ์ดํŠธ:

๋Œ“๊ธ€๋‚จ๊ธฐ๊ธฐ