State 끌어올리기

안윤경·2022년 8월 9일
0

react

목록 보기
11/16
post-thumbnail

State 끌어올리기란?


  • 상위 컴포넌트의 "상태를 변경하는 함수" 그 자체를 하위 컴포넌트로 전달하고, 이 함수를 하위 컴포넌트가 실행한다
  • 여전히 단방향 데이터 흐름의 원칙에 부합하는 해결 방법입니다. 바로 이것이 "상태 끌어올리기" 입니다.

예시를 보며 알아봅시다

import React, { useState } from "react"; 

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

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

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

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

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

위의 예제에서 상태를 변경하는 함수는 무엇인가요? 하위 컴포넌트로는 어떻게 전달할 수 있을까요?

  • 상태를 변경하는 함수는 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>
)
}

필요에 따라 설정할 값을 콜백 함수의 인자로 넘길 수도 있습니다.

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

const handleChangeValue = (newValue) => {
  setValue(newValue);
};

// ...생략...
}

function ChildComponent({ handleButtonClick }) {
const handleClick = () => {
  handleButtonClick('넘겨줄게 자식이 원하는 값')
}

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

이렇게 나오게 됩니다
밑에 다른 예시를 풀어봅시다.

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 />
    <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에 전달되어야 합니다.
  
};

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;

라는 문제가 있습니다

<여기서 고쳐야 할 것>
1.이 상태 변경 함수가 NewTweetForm에 의해 실행되어야 합니다. 이문장의 < NewTweetForm />에는 prop가 없습니다 그러므로 < NewTweetForm onButtonClick={addNewTweet}/>를 넣어줍니다
2. TDOO: 여기서 newTweet이 addNewTweet에 전달되어야 합니다.라는 문장안에
onButtonClick(newTweet)가들어와야함

profile
프론트엔드 개발자 안윤경입니다

0개의 댓글