코드스테이츠 8주차 / [React] 데이터 흐름, 상태 끌어올리기
✏️Achievement Goals
React 데이터 흐름
✅ React에서의 데이터 흐름, 단방향 데이터 흐름을 이해할 수 있다.
✅ 어떤 컴포넌트에 state가 위치해야 하는지 알 수 있다.
✅ State 끌어올리기의 개념을 이해할 수 있다.
✅ 상태 변경 함수가 정의된 컴포넌트와, 상태 변경 함수를 호출하는 컴포넌트가 다름을 알 수 있다.
📝summary
React의 개발 방식의 가장 큰 특징은 페이지 단위가 아닌, 컴포넌트 단위로 시작한다는 점이 가장 큰 특징이다
그림과 같이 앱의 프로토타입을 전달받았다면 먼저 컴포넌트를 먼저 만들고 조립하는 상향식으로 앱을 만든다
장점은 테스트가 쉽고 확장성이 좋다
트위터 클론 Twittler을 그림과 같은 형태로 컴포넌트 디자인을 해보자
저렇게 컴포넌트를 나눈 이유는 하나의 컴포넌트는 한가지 일만 하는 단일 책임 원칙에 따른 구분이다
위를 트리 구조로 나타내면 다음 그림과 같다
데이터를 어디에 둘지를 결정하자
컴포넌트는 컴포넌트 바깥에서 props를 이용해 데이터를 마치 인자(arguments) 혹은 속성(attributes)처럼 전달받을 수 있다
즉 데이터를 전달하는 주체는 부모 컴포넌트가 되고
이는 데이터 흐름이 하향식(top-down)임을 의미한다
단방향 데이터 흐름(one-way data flow)이라는 키워드가 React를 대표하는 설명 중 하나일 정도 아주 중요하다
또한 컴포넌트는 props를 통해 전달받은 데이터가 어디서 왔는지 알지 못한다
상태위치 정하기
상태가 특정 컴포넌트에서만 사용된다면 특정 컴포넌트에만 두면 되니까 어렵지 않다
하지만 하나의 상태를 기반으로 두 컴포넌트가 영향을 받는다면 이 때에는 공통 소유 컴포넌트를 찾아 그 곳에 상태를 위치시켜야 한다
즉, 두 개의 자식 컴포넌트가 하나의 상태에 접근하고자 할 때는 두 자식의 공통 부모 컴포넌트에 상태를 위치시켜야 한다
"전체 트윗 목록" 위치정하기
전체 트윗 목록은, Tweets에서 필요로 하고
새 글을 추가하는 이벤트가 발생할 경우, 이때에 전체 트윗 목록에 새로운 트윗 객체를 추가할 수 있어야 한다
Tweet와 NewTweetForm 두 컴포넌트 모두 트윗 목록에 의존한다
그러므로 전체 트윗 목록 상태는 두 컴포넌트의 부모인 Twittler에 위치한다
"사용자가 작성중인 새로운 트윗 내용" 상태 위치정하기
사용자 입력에 따라 값이 변하므로 "작성중인 트윗 내용"은 상태이고
NewTweetForm에서는 사용자가 트윗 내용을 작성할 수 있다
다른 곳에서는 필요하지 않으므로 NewTweetForm에 위치하면 된다
역방향 데이터 흐름
상태 위치를 전부 정하고 나면 부모 컴포넌트에서의 상태가 하위 컴포넌트에 의해 변하는 경우가 있다
이 예시에서는 새로운 트윗 추가가 대표적이고 버튼을 통해서 부모에게 새 트윗을 추가하는
부모의 상태를 변화시켜야 한다
이것을 해결하기 위해 "State 끌어올리기(Lifting state up)"를 사용한다
상태를 변경시키는 함수(handler)를 하위 컴포넌트에 props로 전달해서 해결할 수 있다
이는 마치 콜백 함수를 사용하는 방법과 비슷하다
State 끌어올리기 (Lifting State Up)
상위 컴포넌트의 "상태를 변경하는 함수" 그 자체를 하위 컴포넌트로 전달하고, 이 함수를 하위 컴포넌트가 실행한다
부모와 자식 컴포넌트가 하나씩 존재하는 트리 구조이고
그리고, 상태를 변경시킬 수 있는 메소드가 존재하면
다음과 같은 구성을 가지게 된다
여기서 버튼을 클릭해 부모의 글씨를 바꿔보자
상태를 변경하려는 함수 자체를 하위컴포넌트로 전달해야 한다고 했으므로
상태를 변경해야 하는 함수는 handleChangeValue 이고
전달은 props를 이용한다
하위 컴포넌트가 버튼 클릭 이벤트에 따라 상태를 변경하니 이름은 handleButtonClick이라고 지어줬다
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>;
}
해설
import React, { useState } from "react";
export default function ParentComponent() {
const [value, setValue] = useState("날 바꿔줘!");
const handleChangeValue = () => {
setValue("보여줄게 완전히 달라진 값");
};
return (
<div>
<div>값은 {value} 입니다</div>
<ChildComponent handleButtonClick={handleChangeValue} />
// 1번
// 상태를 변경하려는 함수 자체를 하위컴포넌트로 전달해야 한다고 했으므로
// 상태를 변경해야 하는 함수는 handleChangeValue 이고
// 전달은 props를 이용한다
// 하위 컴포넌트가 버튼 클릭 이벤트에 따라 상태를 변경하니
// 이름은 handleButtonClick이라고 지어줬다
</div>
);
}
function ChildComponent({ handleButtonClick }) {
// 2번 props로 함수를 전달 받아온다
const handleClick = () => {
// 이 버튼을 눌러서 부모의 상태를 바꿀 순 없을까?
handleButtonClick();
// 3번
// ChildComponent는 마치 고차함수가 인자로 받은 함수를 실행하듯,
// props로 전달받은 함수를 컴포넌트 내에서 실행할 수 있게 된다
// "상태 변경 함수"는 버튼이 클릭할 때 실행되기를 원하므로, 해당 부분에 콜백 함수를 실행하면 작동한다
};
return <button onClick={handleClick}>값 변경</button>;
}
Author And Source
이 문제에 관하여(코드스테이츠 8주차 / [React] 데이터 흐름, 상태 끌어올리기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@support/코드스테이츠-8주차-React-데이터-흐름의-이해와-비동기-요청-처리저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)