Framework/React ์™„๋ฒฝ ๊ฐ€์ด๋“œ

[React ์™„๋ฒฝ ๊ฐ€์ด๋“œ] section 4 : ๋ฆฌ์•กํŠธ State ๋ฐ ์ด๋ฒคํŠธ ๋‹ค๋ฃจ๊ธฐ

yuri lee 2022. 9. 15. 07:44
๋ฐ˜์‘ํ˜•
์ด ๊ธ€์€ udemy์˜ React ์™„๋ฒฝ ๊ฐ€์ด๋“œ with Redux, Next.js, TypeScript ๊ฐ•์ขŒ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

48. ๋ชจ๋“ˆ ์†Œ๊ฐœ

  • User Interaction & State, Making Apps Interactive & Reactive
  • Handking Events
  • Updating the UI & Working with "State"
  • A Closer Look At Components & State

49. ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋‹ ๋ฐ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์ˆ˜ํ–‰ํ•˜๊ธฐ 

  • how to add an event listner to a React element
  <button onClick={() => {console.log("Clicked!!")}}>Change Title</button>
  • ()๋ฅผ ์ œ์™ธํ•˜๊ณ  clickHandler ๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค. ๋งŒ์•ฝ ()๋ฅผ ํ•จ๊ป˜ ๋ช…์‹œํ•  ๊ฒฝ์šฐ, JavaScript would execute this when this line of code is being parsed. So it is then not executing clickHandler when the click occurs but when this JSX code is evaluated. and that would be too early. 
  // function clickHandler() {}
  
  const clickHandler = () => {
    console.log("Clicked!!!")
  }
  
  
  <button onClick={clickHandler}>Change Title</button>  //O
  <button onClick={clickHandler()}>Change Title</button> // X

50.  ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋Šฅ์ด ์‹คํ–‰๋˜๋Š” ๋ฐฉ๋ฒ•

  • ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์˜€์„ ๋•Œ, clickHandler๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์™œ ๊ทธ๋Ÿด๊นŒ? ๋ฆฌ์•กํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฆฌ์•กํŠธ๊ฐ€ JSX ์ฝ”๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ์ „๋‹ฌํ•˜์—ฌ ํ™”๋ฉด์— ๋ถˆ๋Ÿฌ์˜ค๋Š”์ง€์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด์ž. 
const ExpenseItem = (props) => {

  let title = props.title;

  const clickHandler = () => {
    // console.log("Clicked!!!")
    title = 'updatedddd'
    console.log("title", title) // updatedddd
  }

  return (
    <Card className="expense-item">
      <ExpenseDate date={props.date} />
      <div className="expense-item__description">
        <h2>{title}</h2>
        <div className="expense-item__price">${props.amount}</div>
      </div>
      <button onClick={clickHandler}>Change Title</button>
    </Card>
  );
}
export default ExpenseItem;
  • ์ปดํฌ๋„ŒํŠธ๋“ค์€ ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜์ด๊ณ , ๊ทธ ํ•จ์ˆ˜์— ๋Œ€ํ•ด ์œ ์ผํ•˜๊ฒŒ ํŠน๋ณ„ํ•œ ์ ์€ JSX ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ํ˜ธ์ถœํ•  ์ปดํฌ๋„ŒํŠธ ์ฝ”๋“œ๊ฐ€ ๋” ์ด์ƒ ๋‚จ์•„์žˆ์ง€ ์•Š์„ ๋•Œ๊นŒ์ง€ JSX ์ฝ”๋“œ๋ฅผ ํ†ต๊ณผํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  DOM ๋ช…๋ น์–ด๋กœ ๋ฒˆ์—ญํ•ด์„œ ํ™”๋ฉด์— ๋ณด์—ฌ์ง€๋Š” ๊ฒƒ๋“ค์„ ๋ Œ๋”๋งํ•œ๋‹ค. ์ด๊ฒŒ ๋ฆฌ์•กํŠธ๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. 
  • App Component๊ฐ€ ์ฒ˜์Œ์— ์ง€์ •ํ•˜๋Š” index.js ํŒŒ์ผ์—์„œ ์‹œ์ž‘๋œ๋‹ค. ์ด๊ฒŒ ๋ฐ”๋กœ ํ˜ธ์ถœ๋˜๋Š” ์ฒซ ๋ฒˆ์งธ ์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜์ด๊ณ , ํŽ˜์ด์ง€ ๋ฐฉ๋ฌธ ์‹œ react app์ด ํ™”๋ฉด์— ๋กœ๋“œ๋˜๋ฉด์„œ ๋ฒŒ์–ด์ง€๋Š” ์ผ์ด๋‹ค. 

๐Ÿ‘พ ๋ฌธ์ œ! 

  • ๋ฆฌ์•กํŠธ๋Š” ์ ˆ๋Œ€ ๋ฐ˜๋ณตํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค. application์ด ์ฒ˜์Œ ๋ Œ๋”๋ง ๋˜์—ˆ์„ ๋•Œ ๊ทธ ๋ชจ๋“  ๊ณผ์ •์„ ์‹คํ–‰ํ•˜๊ณ , ๊ทธ ์ดํ›„์—๋Š” ๋์ด๋‹ค.  ํ•˜์ง€๋งŒ ์‚ฌ์šฉ์ž๋“ค์€ ํ™”๋ฉด์— ๋ณด์ด๋Š” ๊ฒƒ์„ ๋ฐ”๋กœ ์—…๋ฐ์ดํŠธ ํ•˜๊ณ  ์‹ถ์–ดํ•œ๋‹ค. (ex. ๋ฒ„ํŠผ์ด ํด๋ฆญ ๋˜๋ฉด ํ…์ŠคํŠธ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ ๋“ฑ.. etc) ์ด๋ฅผ ์œ„ํ•ด ์ƒ๊ฒจ๋‚œ ๊ฐœ๋…์ด ๋ฐ”๋กœ state ์ด๋‹ค. 

51. "State"์™€ ํ•จ๊ป˜ ์ผํ•˜๊ธฐ

  • "useState" : ๋ฆฌ์•กํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜๋กœ, ์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋˜๋Š” ๊ณณ์—์„œ ๋ณ€๊ฒฝ๋œ ๊ฐ’์„ ๋ฐ˜์˜ํ•˜๊ธฐ ์œ„ํ•ด state๋กœ ๊ฐ’์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. 
import React, {  useState} from 'react';
import "./ExpenseItem.css";
import ExpenseDate from "./ExpenseDate";
import Card from "../UI/Card";

const ExpenseItem = (props) => {
  const [title, setTitle] = useState(props.title);

  const clickHandler = () => {
    setTitle("Updated!");
    console.log("title", title)
    // ์—ฌ์ „ํžˆ ์ „์˜ props.title ๊ฐ’์ด ํ˜ธ์ถœ๋˜๋Š” ์ด์œ ๋Š”, state๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ 
    // ์‚ฌ์‹ค์ƒ ๋ฐ”๋กœ ๊ฐ’์„ ๋ฐ”๊พธ์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ. ๋Œ€์‹  ์ด state์˜ ์—…๋ฐ์ดํŠธ๋ฅผ ์˜ˆ์•ฝํ•œ๋‹ค. 
    // ์•„๋ž˜์˜ ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์‹œ ํ˜ธ์ถœ๋˜์–ด ์žฌ ํ‰๊ฐ€๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ™”๋ฉด์—์„œ๋Š” ์—…๋ฐ์ดํŠธ ๋œ ๊ฐ’์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 
  }

  return (
    <Card className="expense-item">
      <ExpenseDate date={props.date} />
      <div className="expense-item__description">
        <h2>{title}</h2>
        <div className="expense-item__price">${props.amount}</div>
      </div>
      <button onClick={clickHandler}>Change Title</button>
    </Card>
  );
}
export default ExpenseItem;

  • useState๋Š” ๋ฆฌ์•กํŠธ ํ›…์ด๋ผ๊ณ ๋„ ๋ถˆ๋ฆฐ๋‹ค. ๋ชจ๋“  ํ›…์€ ์ด๋ฆ„์ด "use"์œผ๋กœ ์‹œ์ž‘ํ•œ๋‹ค
  • ์ตœ์‹  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋ฐฐ์—ด ๊ตฌ์กฐ ๋ถ„ํ•ด๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰ useState๋Š” ํ•ญ์ƒ 2๊ฐœ์˜ ์š”์†Œ๊ฐ€ ์žˆ๋Š” ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋Š” ํ˜„์žฌ ์ƒํƒœ๊ฐ’์ด๊ณ , ๋‘ ๋ฒˆ์งธ ์š”์†Œ๋Š” ์ด๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. 
  • state๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ? ์–ด๋–ค ๋ณ€์ˆ˜์— ์ƒˆ๋กœ์šด ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋ฉ”๋ชจ๋ฆฌ ์–ด๋”˜๊ฐ€์—์„œ ๋ฆฌ์•กํŠธ๋กœ ๊ด€๋ฆฌ๋œ๋‹ค. 

52.  "useState" ํ›… ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ธฐ

  • state๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์ธ์Šคํ„ด์Šค๋ณ„๋กœ ๋‚˜๋‰˜์–ด์ ธ ์žˆ๋‹ค. 
  • const ์ƒ์ˆ˜ํ˜•์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ? ๊ธฐ์–ตํ•ด์•ผ ํ•  ๊ฒƒ์€ ๋“ฑํ˜ธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ’์„ ํ• ๋‹นํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋Œ€์‹  state๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ๊ตฌ์ฒด์ ์ธ ๊ฐ’์€ ๋ฆฌ์•กํŠธ์— ์˜ํ•ด ์–ด๋”˜๊ฐ€์—์„œ ๊ด€๋ฆฌ๋œ๋‹ค.  ๋”ฐ๋ผ์„œ const ๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๊ดœ์ฐฎ๋‹ค. 
  • useState๋ฅผ ์‚ฌ์šฉํ•ด์„œ state๋ฅผ ๋“ฑ๋กํ•˜๋ฉด ํ•ญ์ƒ 2๊ฐœ์˜ ์š”์†Œ๋ฅผ ์–ป๋Š”๋ฐ, ์ด๋Š” state value์™€ ์ด๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” function ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  state๊ฐ€ ๋ณ€ํ•  ๋•Œ๋งˆ๋‹ค update function์„ ํ˜ธ์ถœํ•œ๋‹ค. JSX์ฝ”๋“œ์—์„œ๋Š” ์ด๋ฅผ ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•ด ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๋ฆฌ์•กํŠธ๋Š” ์ƒํƒœ๊ฐ€ ๋ณ€ํ• ๋•Œ๋งˆ๋‹ค ์ปดํฌ๋„ŒํŠธํ˜• function์„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๊ณ  JSX๋ฅผ re-evaluate ํ•œ๋‹ค. 

53. State๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋  ์ˆ˜ ์žˆ๋‹ค. 

  • user event ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์–ด๋–ค ์ด์œ ๋กœ๋“  ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ๋‹ค. (ex. ํƒ€์ด๋จธ๊ฐ€ ๋งŒ๋ฃŒ๋˜์–ด ์ƒํƒœ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ๋“ฑ etc..)

54. ์–‘์‹ ์ž…๋ ฅ ์ถ”๊ฐ€ํ•˜๊ธฐ

  • NewExpense ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€ 

55.  ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๋ฆฌ์Šค๋‹ (listening)

  • Since we passed this function to react basically, CRUD is on change prop, react we'll make sure or actually even the browser itself will make sure that we get such a event object when this change event occurs.
  // document.getElementById('').addEventListener('click', (event) => { }) ์ „ํ†ต์ ์ธ javascript

  const titleChangeHandler = (event) => {
    console.log("event", event.target.value);
  };

56. ์—ฌ๋Ÿฌ State ๋‹ค๋ฃจ๊ธฐ

  • By the way, I'm storing strings all the time and not a number here for the amount, for example, because by default, whenever you listen to the change event for an input, if you read the value of that input element, it'll always be a string. Even if it stores a number it will be a number as a string and the same for the date.
  const [enteredTitle, setEnteredTitle] = useState("");
  const [enteredAmount, setEnteredAmount] = useState("");
  const [enteredDate, setEnteredDate] = useState("");

  const titleChangeHandler = (event) => {
    setEnteredTitle(event.target.value);
  };

  const amountChangeHandler = (event) => {
    setEnteredAmount(event.target.value);
  };

  const dateChangeHandler = (event) => {
    setEnteredDate(event.target.value);
  };

57. State ๋Œ€์‹  ์‚ฌ์šฉํ•˜๊ธฐ 

  • 3๊ฐœ์˜ ๋…๋ฆฝ์ ์ธ state๊ฐ€ ์•„๋‹ˆ๋ผ ํ•œ ๊ฐœ์˜ state๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด state๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ๋•Œ๋งˆ๋‹ค 1๊ฐœ๊ฐ€ ์•„๋‹ˆ๋ผ 3๊ฐœ ํ”„๋กœํผํ‹ฐ ๋ชจ๋‘๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์•ผ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋‚˜๋จธ์ง€ 2๊ฐœ์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์žƒ์–ด๋ฒ„๋ฆฌ์ง€ ์•Š๋„๋ก ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค. ๋ฆฌ์•กํŠธ์—์„œ state๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๋•Œ๋Š” ์ด์ „ state์™€ ๋ณ‘ํ•ฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋‹จ์ˆœํžˆ ์˜ˆ์ „ state๋ฅผ ์ƒˆ state๋กœ ๋Œ€์ฒดํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์—…๋ฐ์ดํŠธ ํ•˜์ง€ ์•Š๋Š” ๋‹ค๋ฅธ ๊ฐ’๋“ค์€ ์ˆ˜๋™์œผ๋กœ ๋ณต์‚ฌํ•ด์•ผ ํ•œ๋‹ค. 
  const [userInput, setUserInput] = useState({
    enteredTitle: "",
    enteredAmount: "",
    enteredDate: "",
  });

  const titleChangeHandler = (event) => {
    setUserInput({
      ...userInput,
      enteredTitle: event.target.value,
    });
  };

  const amountChangeHandler = (event) => {
    setUserInput({
      ...userInput,
      enteredAmount: event.target.value,
    });
  };

  const dateChangeHandler = (event) => {
    setUserInput({
      ...userInput,
      enteredDate: event.target.value,
    });
  };

๐Ÿ‘พ ๋ฌธ์ œ! 

  • One thing is not fine though, And that is how I update my state here. When I also consider my oldest state for copying in values.

58. ์ด์ „ State์— ์˜์กดํ•˜๋Š” State ์—…๋ฐ์ดํŠธ 

  • ์•„๋ž˜์˜ ๋‘ ๋ฐฉ๋ฒ•์€ ๋ชจ๋‘ ๊ดœ์ฐฎ์ง€๋งŒ, ์ด๋ก ์ ์œผ๋กœ ๋™์‹œ์— ์ˆ˜๋งŽ์€ state update๋ฅผ ๊ณ„ํšํ•œ๋‹ค๋ฉด ์˜ค๋ž˜๋˜์—ˆ๊ฑฐ๋‚˜ ์ž˜๋ชป๋œ state snapshot์— ์˜์กดํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‘๋ฒˆ์งธ ์ ‘๊ทผ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด, ๋ฆฌ์•กํŠธ๋Š” ์ด ์•ˆ์— ์žˆ๋Š” ํ•จ์ˆ˜์—์„œ ์ด state snapshot์ด ๊ฐ€์žฅ ์ตœ์‹ ์˜  state snapshot๋ผ๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•ญ์ƒ ์ตœ์‹  ์ƒํƒœ์˜ snapshot์—์„œ ์ž‘์—…ํ•˜๋„๋ก ํ•˜๋Š” ์กฐ๊ธˆ ๋” ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค. 
  const titleChangeHandler = (event) => {
    // setUserInput({
    //   ...userInput,
    //   enteredTitle: event.target.value,
    // });

    setUserInput((prevState) => {
      return { ...prevState, enteredTitle: event.target.value };
    });
  };

59.  ์–‘์‹ ์ œ์ถœ ์ฒ˜๋ฆฌ

  • ์ž…๋ ฅ ํƒ€์ž…์ด submit ์ผ ๊ฒฝ์šฐ, submit event ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํŽ˜์ด์ง€๊ฐ€ ๋‹ค์‹œ ๋กœ๋“œ ๋  ๊ฒƒ์ด๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋Š” form์ด ์ œ์ถœ๋  ๋•Œ๋งˆ๋‹ค ์ด ์›นํŽ˜์ด์ง€๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜๊ณ  ์žˆ๋Š” ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋”ฐ๋ผ์„œ ์ด ๊ธฐ๋ณธ ๋™์ž‘์„ event.preventDefault() ๋ฅผ ํ†ตํ•ด ๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค. 
  const submitHandler = (event) => {
    event.preventDefault();
    console.log("submit");

    const expenseDate = {
      title: enteredTitle,
      amount: enteredAmount,
      date: new Date(enteredDate),
    };

    console.log("expenseDate", expenseDate);
  };
  
  
  return (
  	<form onSubmit={submitHandler}> ...
  )

60.  ์–‘๋ฐฉํ–ฅ ๋ฐ”์ธ๋”ฉ ์ถ”๊ฐ€

  • Two-way binding is very useful when you're working with forms because it allows you to gather user input, but then also change it.

61. ์ž์‹ ๋Œ€ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ ํ†ต์‹ (์ƒํ–ฅ์‹)

  • ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•

62. State ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ

  • NewExpense ์ปดํฌ๋„ŒํŠธ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ „๋‹ฌํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹ˆ๊ณ , ๋Œ€์‹  ExpenseForm ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. State๋กœ ์ž‘์—…ํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ๊ฐ€์ ธ์™€์„œ ์ €์žฅํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ์ปดํฌ๋„ŒํŠธ๋Š” ๋ถˆ๋Ÿฌ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ NewExpense ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•œ๋‹ค. 
  • ํ•ญ์ƒ ๋ฃจํŠธ App ์ปดํฌ๋„ŒํŠธ๊นŒ์ง€ ์ƒํƒœ๋ฅผ ๋Œ์–ด์˜ฌ๋ ค์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๋Œ€์‹  ์ปดํฌ๋„ŒํŠธ tree์—์„œ ํ•„์š”ํ•œ ๋งŒํผ ๋Œ์–ด์˜ฌ๋ฆฌ๋Š”๋ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์™€ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ๋œ๋‹ค. 

63. ์—ฐ์Šตํ•˜๊ธฐ : ์ด๋ฒคํŠธ ๋ฐ state ์ž‘์—…ํ•˜๊ธฐ 

  • ๊ฐ•์˜ ํ™•์ธ

64. ์—ฐ์Šตํ•˜๊ธฐ : ์ด๋ฒคํŠธ ๋ฐ state ์ž‘์—…ํ•˜๊ธฐ (answer)

  • ๊ฐ•์˜ ํ™•์ธ 

65. ์ œ์–ด๋œ ์ปดํฌ๋„ŒํŠธ์™€ ์ œ์–ด๋˜์ง€ ์•Š์€ ์ปดํฌ๋„ŒํŠธ ๋ฐ Stateless ์ปดํฌ๋„ŒํŠธ์™€ Stateful ์ปดํฌ๋„ŒํŠธ

  • state๊ฐ€ ๋ฌด์—‡์ธ์ง€
  • ์ด๋ฒคํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•
  • ์ž์‹์—์„œ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•
// before
const ExpenseItem = (props) => {
  const [title, setTitle] = useState(props.title);

  const clickHandler = () => {
    console.log("title", title);
  };

  return (
    <Card className="expense-item">
      <ExpenseDate date={props.date} />
      <div className="expense-item__description">
        <h2>{title}</h2>
        <div className="expense-item__price">${props.amount}</div>
      </div>
      <button onClick={clickHandler}>Change Title</button>
    </Card>
  );
};
export default ExpenseItem;
// after
const ExpenseItem = (props) => {
  return (
    <Card className="expense-item">
      <ExpenseDate date={props.date} />
      <div className="expense-item__description">
        <h2>{props.title}</h2>
        <div className="expense-item__price">${props.amount}</div>
      </div>
    </Card>
  );
};
export default ExpenseItem;

66. ๋ชจ๋“ˆ ๋ฆฌ์†Œ์Šค 

  • ๊ฐ•์˜ ํ™•์ธ 

https://www.udemy.com/course/best-react/

๋ฐ˜์‘ํ˜•