codeStates front-end/React

[React] ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ & Controlled Component & React ๋ฐ์ดํ„ฐ ํ๋ฆ„

ํ™˜ํ…Œํฌ 2023. 1. 26. 14:08
๋ฐ˜์‘ํ˜•

 

 

 

 

 

๐Ÿ“Œ๋ฆฌ์•กํŠธ ๊ฐœ๋…

 

 

๐Ÿ“์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ( Event handling )

 

React ์—์„œ ์ด๋ฒคํŠธ๋Š” ์†Œ๋ฌธ์ž ๋Œ€์‹  ์นด๋ฉœ ์ผ€์ด์Šค๋ฅผ ์‚ฌ์šฉ

JSX๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด์ด ์•„๋‹Œ ํ•จ์ˆ˜๋กœ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌ

 

<button onclick="handleEvent()">Event</button> // html
<button onClick={handleEvent}>Event</button> // react

 

 

 

๐Ÿ”— onChange

 

ํผ(Form) ์—˜๋ฆฌ๋จผํŠธ (<input><textarea><select>) ๋Š” ์ž…๋ ฅ๊ฐ’์„ ์ œ์–ดํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ

๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ์ž…๋ ฅ๊ฐ’ -> ์ปดํฌ๋„ŒํŠธ์˜ state๋กœ ๊ด€๋ฆฌ

 

function NameForm() {
  const [name, setName] = useState("");

  const handleChange = (e) => {
    setName(e.target.value); // onChange ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด e.target.value๋ฅผ ํ†ตํ•ด input ๊ฐ’์„ ์ฝ์–ด์˜ด
  }

  return (
    <div>
    {/* inputํƒœ๊ทธ ์•ˆ์— value์™€ onChange(ํ…์ŠคํŠธ๊ฐ€ ๋ฐ”๋€” ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ)๋ฅผ ๋„ฃ์–ด์คŒ
    	์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด handleChange ํ•จ์ˆ˜๊ฐ€ ์ž‘๋™ ์ƒˆ๋กœ์šด state๋กœ ๊ฐฑ์‹  */}
      <input type="text" value={name} onChange={handleChange}></input> 
      <h1>{name}</h1>
    </div>
  )
};

 

 

 

onChange ์‹ค์Šต

 

 

import React, { useState } from "react";
import "./styles.css";

function SelectExample() {
  const [choice, setChoice] = useState("apple");

  const fruits = ["apple", "orange", "pineapple", "strawberry", "grape"];
  const options = fruits.map((fruit) => {
    return <option value={fruit}>{fruit}</option>;
  });
  console.log(choice);
  const handleFruit = (event) => {
    setChoice(event.target.value);
  };

 

 

 

์‹คํ–‰๊ฒฐ๊ณผ

 

 

์˜ต์…˜์„ ์„ ํƒํ•  ๋•Œ๋งˆ๋‹ค text๊ฐ€ ๋ณ€๊ฒฝ๋จ์ด ํ™•์ธ ๊ฐ€๋Šฅํ•˜๋‹ค

 

 

๐Ÿ”— onClick

 

์‚ฌ์šฉ์ž๊ฐ€ ํด๋ฆญ์ด๋ผ๋Š” ํ–‰๋™์„ ํ•˜์˜€์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ

 

function NameForm() {
  const [name, setName] = useState("");

  const handleChange = (e) => {
    setName(e.target.value);
  }

  return (
    <div>
    {/* input tag ์— ์ž…๋ ฅํ•œ ์ด๋ฆ„์ด alert์„ ํ†ตํ•ด ์•Œ๋ฆผ ์ฐฝ์ด ํŒ์—… ๋˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ */}
      <input type="text" value={name} onChange={handleChange}></input>
      <button onClick={alert(name)}>Button</button>
      <h1>{name}</h1>
    </div>
  );
};

 

 

onClick ์ด๋ฒคํŠธ์— ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ๋•Œ๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฆฌํ„ด๋ฌธ ์•ˆ์—์„œ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ฑฐ๋‚˜

๋ฆฌํ„ด๋ฌธ ์™ธ๋ถ€์—์„œ ํ•จ์ˆ˜๋ฅผ ์ •์˜ ํ›„ ์ด๋ฒคํŠธ์— ํ•จ์ˆ˜ ์ž์ฒด๋ฅผ ์ „๋‹ฌ

 

// ํ•จ์ˆ˜ ์ •์˜ํ•˜๊ธฐ

return (
  <div>
	...
    <button onClick={() => alert(name)}>Button</button>
	...
  </div>
  );
};

// ํ•จ์ˆ˜ ์ž์ฒด๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ

const handleClick = () => {
  alert(name);
};

return (
  <div>
      ...
    <button onClick={handleClick}>Button</button>
      ...
  </div>
  );
};

 

 

onClick ์‹ค์Šต

 

 

import "./styles.css";
import React, { useState } from "react";

function NameForm() {
  const [name, setName] = useState("");

  const handleChange = (e) => {
    setName(e.target.value);
  };

  const handleClick = () => {
    alert(name);
  };
  return (
    <div className="App">
      <h1>Event handler practice</h1>
      <input type="text" value={name} onChange={handleChange}></input>
      <button onClick={handleClick}>Button</button> // ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ(์ด ๋ฐฉ๋ฒ•์„ ๋” ์„ ํ˜ธ)
      <button onClick={() => alert(name)}>Button</button> // ํ•จ์ˆ˜๋ฅผ ์„ ์–ธ ๋ฐ ํ˜ธ์ถœ
      <h3>{name}</h3>
    </div>
  );
}
export default NameForm;

 

 

์‹คํ–‰ ๊ฒฐ๊ณผ ๋‘๊ฐ€์ง€ ๋ฒ„ํŠผ ๋ชจ๋‘ alert์ด ๋œจ๋Š” ๊ฒƒ์ด ํ™•์ธ ๊ฐ€๋Šฅํ•˜๋‹ค

 

 

 

 

popup ์‹ค์Šต

 

 

import React, { useState } from "react";
import "./styles.css";

function App() {
  const [showPopup, setShowPopup] = useState(false);

  const togglePopup = (e) => {
    // Pop up ์˜ open/close ์ƒํƒœ์— ๋”ฐ๋ผ
    // ํ˜„์žฌ state ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋˜๋„๋ก ํ•จ์ˆ˜๋ฅผ ์™„์„ฑํ•˜์„ธ์š”.
    if (showPopup === false) {
      setShowPopup(true);
    } else setShowPopup(false);
  };

  return (
    <div className="App">
      <h1>Fix me to open Pop Up</h1>
      {/* ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ Pop up ์˜ open/close ๊ฐ€ ์ž‘๋™ํ•˜๋„๋ก
          button tag๋ฅผ ์™„์„ฑํ•˜์„ธ์š”. */}
      <button className="open" onClick={togglePopup}>
        Open me
      </button>
      {showPopup ? (
        <div className="popup">
          <div className="popup_inner">
            <h2>Success!</h2>
            <button className="close" onClick={togglePopup}>
              Close me
            </button>
          </div>
        </div>
      ) : null}
    </div>
  );
}

export default App;

 

 

์‹คํ–‰๊ฒฐ๊ณผ

 

 

 

 

 

 

๐Ÿ”—Controlled Component

 

๋ฆฌ์•กํŠธ๊ฐ€ state์„ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ปจํŠธ๋กค ์ปดํฌ๋„ŒํŠธ๋ผ๊ณ ํ•œ๋‹ค.

 

 

 

controlled component ์‹ค์Šต

 

 

import "./styles.css";
import React, { useState } from "react";

export default function App() {
  const [username, setUsername] = useState("");
  const [msg, setMsg] = useState("");

  return (
    <div className="App">
      <div>{username}</div>
      <input
        type="text"
        value={username}
        onChange={(event) => setUsername(event.target.value)} // ์ปจํŠธ๋กค ์ปดํฌ๋„ŒํŠธ
        placeholder="์—ฌ๊ธฐ๋Š” ์ธํ’‹์ž…๋‹ˆ๋‹ค."
        className="tweetForm__input--username"
      ></input>
      <div>{msg}</div>
      {/* TODO : ์œ„ input๊ณผ ๊ฐ™์ด ์ž…๋ ฅ์— ๋”ฐ๋ผ์„œ msg state๊ฐ€ ๋ณ€ํ•  ์ˆ˜ ์žˆ๊ฒŒ 
      ์•„๋ž˜ textarea๋ฅผ ๋ณ€๊ฒฝํ•˜์„ธ์š”. */}
      <textarea
        placeholder="์—ฌ๊ธฐ๋Š” ํ…์ŠคํŠธ ์˜์—ญ์ž…๋‹ˆ๋‹ค."
        className="tweetForm__input--message"
        onChange={(event) => setMsg(event.target.value)}
        value={""}
      ></textarea>
    </div>
  );
}

 

 

 

์‹คํ–‰ ๊ฒฐ๊ณผ

 

 

 

 

 

 

 

๐Ÿ”— React ๋ฐ์ดํ„ฐ ํ๋ฆ„

 

ํŽ˜์ด์ง€ ๋‹จ์œ„ x -> ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„ o

์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ๋‹ค์‹œ ํŽ˜์ด์ง€๋ฅผ ์กฐ๋ฆฝ

์ปดํฌ๋„ŒํŠธ๋Š” ์ƒํ–ฅ์‹(bottom-up)์œผ๋กœ ์ œ์ž‘ -> ํ…Œ์ŠคํŠธ๊ฐ€ ์‰ฝ๊ณ  ํ™•์žฅ์„ฑ์ด ์ข‹๋‹ค

ํŠธ๋ฆฌ๊ตฌ์กฐ๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค

๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋””์— ๋‘˜์ง€ ๊ฒฐ์ •

์ปดํฌ๋„ŒํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ๋ฐ”๊นฅ์—์„œ props๋ฅผ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋งˆ์น˜ ์ธ์ž ํ˜น์€ ์†์„ฑ ์ฒ˜๋Ÿผ

์ „๋‹ฌ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์ฃผ์ฒด -> ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ : ๋ฐ์ดํ„ฐ ํ๋ฆ„์ด ํ•˜ํ–ฅ์‹(top-down)์ž„์„ ์˜๋ฏธ

๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„(one-way data flow)

์ปดํฌ๋„ŒํŠธ๋Š” props๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋””์„œ ์™”๋Š”์ง€ ์•Œ ์ˆ˜ ์—†์Œ

์ƒํƒœ๋Š” ์ตœ์†Œํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค(๋ณต์žก์„ฑ ๋•Œ๋ฌธ)

 

- ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ props๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ๋ฉ๋‹ˆ๊นŒ? ๊ทธ๋Ÿฌ๋ฉด ํ™•์‹คํžˆ state๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

- ์‹œ๊ฐ„์ด ์ง€๋‚˜๋„ ๋ณ€ํ•˜์ง€ ์•Š๋‚˜์š”? ๊ทธ๋Ÿฌ๋ฉด ํ™•์‹คํžˆ state๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

- ์ปดํฌ๋„ŒํŠธ ์•ˆ์˜ ๋‹ค๋ฅธ state๋‚˜ props๋ฅผ ๊ฐ€์ง€๊ณ  ๊ณ„์‚ฐ ๊ฐ€๋Šฅํ•œ๊ฐ€์š”? ๊ทธ๋ ‡๋‹ค๋ฉด state๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

 

์ƒํƒœ๋ฅผ ์–ด๋””์— ์œ„์น˜์‹œ์ผœ์•ผ ํ•˜๋Š”์ง€ ์‚ดํŽด๋ด์•ผ ํ•œ๋‹ค

A component , B component -> parent component ๋ผ๋ฉด, parent ์˜ ์ƒํƒœ๋ฅผ ์œ„์น˜

 

 

 

๋ฐ˜์‘ํ˜•