[React] State 끌어올리기

Hannahhh·2022년 8월 9일
0

React

목록 보기
12/30

👀 Lifting State Up


하위 컴포넌트에서의 이벤트로 인해 상위 컴포넌트의 상태가 바뀌게 해야할 때, 상위 컴포넌트의 상태를 변경하는 함수(handler) 그 자체를 하위 컴포넌트에 props로 전달하고, 이 함수를 컴포넌트가 실행하도록 한다. (콜백함수 사용과 비슷하다.)




아래 예제를 보면, 상태 변경 함수는 handleChangeValue 이다. props를 이용해 전달하며, props 이름은 임의로 설정 가능하다. 하위 컴포넌트가 버튼 클릭 이벤트에 따라 상태를 변경하려고 하므로 handleButtonClick 으로 설정했다.

function ParentComponent() {
  const [value, setValue] = useState("날 바꿔줘!");

  const handleChangeValue = () => {
    setValue("보여줄게 완전히 달라진 값");
  };

  return (
    <div>
      <div>값은 {value} 입니다</div>
      <ChildComponent handleButtonClick={handleChangeValue}  />
    </div>
  );
}

아래의 코드는 <ChildComponent> 컴포넌트 내의 코드로, 마치 고차 함수가 인자로 받은 함수를 실행하듯, props로 전달받은 함수를 컴포넌트 내에서 실행할 수 있다.

상태 변경 함수는 버튼이 클릭할 때 실행되기를 원하므로, 해당 부분에 콜백 함수를 실행한다.

function ChildComponent({ handleButtonClick }) {
  const handleClick = () => {
    // Q. 이 버튼을 눌러서 부모의 상태를 바꿀 순 없을까?
    // A. 인자로 받은 상태 변경 함수를 실행하자!

    handleButtonClick()
  }

  return (
    <button onClick={handleClick}>값 변경</button>
  )
}




✔ 예제1

import React, { useState } from "react";

export default function ParentComponent() {
  const [value, setValue] = useState("날 바꿔줘!");

  const handleChangeValue = () => {
    setValue("보여줄게 완전히 달라진 값");
  };

  return (
    <div>
      <div>값은 {value} 입니다</div>
      <ChildComponent handleButtonClick={handleChangeValue}  />
    </div>
  );
}

function ChildComponent({handleButtonClick}) {
  const handleClick = () => {
    // 이 버튼을 눌러서 부모의 상태를 바꿀 순 없을까?
    handleButtonClick()
  };

  return <button onClick={handleClick}>값 변경</button>;
}


값변경 버튼 클릭 시,



✔ 예제2: Twittler


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

const currentUser = "김코딩";

function Twittler() {
  const [tweets, setTweets] = useState([
    {
      uuid: 1,
      writer: "김코딩",
      date: "2020-10-10",
      content: "안녕 리액트"
    },
    {
      uuid: 2,
      writer: "박해커",
      date: "2020-10-12",
      content: "좋아 코드스테이츠!"
    }
  ]);

  const addNewTweet = (newTweet) => {
    setTweets([...tweets, newTweet]);
  }; // 이 상태 변경 함수가 NewTweetForm에 의해 실행되어야 합니다.

  return (
    <div>
      <div>작성자: {currentUser}</div>
      <NewTweetForm onButtonClick= {addNewTweet}/>
      <ul id="tweets">
        {tweets.map((t) => (
          <SingleTweet key={t.uuid} writer={t.writer} date={t.date}>
            {t.content}
          </SingleTweet>
        ))}
      </ul>
    </div>
  );
}

function NewTweetForm({ onButtonClick }) {
  const [newTweetContent, setNewTweetContent] = useState("");

  const onTextChange = (e) => {
    setNewTweetContent(e.target.value);
  };

  const onClickSubmit = () => {
    let newTweet = {
      uuid: Math.floor(Math.random() * 10000),
      writer: currentUser,
      date: new Date().toISOString().substring(0, 10),
      content: newTweetContent
    };
    // TDOO: 여기서 newTweet이 addNewTweet에 전달되어야 합니다.
    onButtonClick(newTweet);
  };

  return (
    <div id="writing-area">
      <textarea id="new-tweet-content" onChange={onTextChange}></textarea>
      <button id="submit-new-tweet" onClick={onClickSubmit}>
        새 글 쓰기
      </button>
    </div>
  );
}

function SingleTweet({ writer, date, children }) {
  return (
    <li className="tweet">
      <div className="writer">{writer}</div>
      <div className="date">{date}</div>
      <div>{children}</div>
    </li>
  );
}

export default Twittler;

0개의 댓글