윤휴먼
ddooyn.log
윤휴먼
전체 방문자
오늘
어제
  • 분류 전체보기 (19)
    • FRONT-END (6)
      • Projects (0)
      • Retrospective (6)
    • HTML CSS (0)
    • JavaScript (6)
    • React (4)
    • Node.js (0)
    • Python (2)
    • Algorithm (0)
    • Tips (1)
    • Books (0)

인기 글

태그

  • AWS
  • jQuery
  • mongodb
  • github
  • javascript
  • PYTHON
  • Tip
  • Next.js
  • react
  • ESLint
  • WIL

최근 댓글

hELLO · Designed By 정상우.
윤휴먼

ddooyn.log

[React] 양방향/단방향 바인딩, 부모 컴포넌트의 state 바꾸기
React

[React] 양방향/단방향 바인딩, 부모 컴포넌트의 state 바꾸기

2022. 7. 4. 18:56

↔ 양방향 바인딩?

AngularJS는 양방향 데이터 바인딩을, React/Vue/Angular는 단방향 데이터 바인딩을 지원한다.

 

양방향 데이터 바인딩에서는 부모 컴포넌트와 자식 컴포넌트 간에 데이터가 서로 양방향으로 흐른다.

부모와 자식 모두 데이터를 직접 변경할 수 있다.

 

model(JavaScript)과 view(HTML)가 있을 때, 양방향 데이터 바인딩은 model이 업데이트 되면 view가 업데이트 되고, 반대로 view가 업데이트되면 model이 업데이트 되는 것이다.

이를 자동 동기화라고도 한다. 상호 구독 관계라고 생각하면 이해하기 쉽다.

양방향 바인딩
단방향 바인딩

 

하지만 변화 가능성이 열려있다 보니 데이터 흐름을 예상하기 어렵다는 단점이 있다.

이같은 단점의 대표적인 사례로 페이스북의 알림 버그가 있다.

 

MVC pattern

 

👇 리액트는 단방향 바인딩

리액트에서 일반적으로 state 관리를 할 때는 props를 통해 부모에서 자식 컴포넌트로의 단방향(하향식) 데이터 흐름이 일어난다. 이로 인해 데이터의 흐름을 명확히 알 수 있고 예측 가능하다.

 

그렇다면 자식에서는 부모 컴포넌트의 state를 변화시킬 수 없을까?

 

물론 바꿀 수 있다.

리액트는 양방향 바인딩을 지원하지 않지만, 예를 들어 자식 컴포넌트에서 event (onChange, onClick, onBlur, …)가 발생할 때 부모 컴포넌트에서 전달한 핸들러를 통해 state를 바꾸는 등의 양방향 바인딩 같은 동작이 일어나도록 하면 된다. 이를 state 끌어올리기(lifting state up)를 통해 구현할 수 있다.

 

https://ko.reactjs.org/docs/lifting-state-up.html

 

State 끌어올리기 – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

💡 부모 컴포넌트의 state를 바꾸는 방법

간단한 예시를 통해 설명하겠다.

부모 컴포넌트는 자식 컴포넌트 1과 자식 컴포넌트 2를 가지고 있다.

자식 컴포넌트 2에서는 리스트를 렌더링하고 있고, 자식 컴포넌트 1에서 리스트에 변화를 주어야 한다.

 

React에서 state를 공유하려면 그 데이터를 필요로 하는 컴포넌트 간의 가장 가까운 부모로 state를 끌어올리면 된다. 즉, 자식 컴포넌트 2에서 state를 가지고 있었다면 그걸 부모 컴포넌트가 가진 뒤 props로 내려주는 것이다.

import { useState } from 'react';
import First from './First';
import Second from './Second';

function App() {
  const [list, setList] = useState(['리스트1']);
  const addList = (value) => {
    setList([...list, value]);
  };

  return (
    <>
      <h1>부모 컴포넌트</h1>
      <First addList={addList} />
      <Second list={list} />
    </>
  );
}

export default App;

이제 부모 컴포넌트가 초깃값이 ['리스트1']인 list state를 가지고 자식 컴포넌트 2로 내려주게 되었다.

 

그렇다면 자식 컴포넌트 1은 어떻게 부모 컴포넌트의 상태를 바꿀 수 있을까?

마찬가지로 부모 컴포넌트에서 상태변화 함수를 만들어 자식 컴포넌트 1로 내려주면 된다.

addList라는 함수에서 기존 list 배열에 매개변수로 받은 value를 추가할 수 있게 setList로 state를 변화시킨다.

import { useRef } from 'react';

const First = ({ addList }) => {
  const text = useRef(null);
  const onClickSubmit = (e) => {
    e.preventDefault();
    addList(text.current.value);
    text.current.value = '';
  };

  return (
    <>
      <h2>자식 컴포넌트 1</h2>
      <form>
        <input type="text" ref={text} />
        <button onClick={onClickSubmit}>추가</button>
      </form>
    </>
  );
};

export default First;

이제 자식 컴포넌트 1로 와서 onClickSubmit 함수를 만들어 주었다.

폼이 submit 됐을 때의 기본 동작을 막기 위해 e.preventDefault()를 한 다음,

props로 내려받은 addList 함수의 인자로 input에 입력한 값을 넣어 주면 부모 컴포넌트의 state를 변화시킬 수 있다. state가 변화한 다음 input 값을 비워주기 위해 text.current.value를 빈 문자열''로 만들어 주었다.

그리고 button의 온클릭 이벤트로 onClickSubmit을 전달한다. 이때 ( )를 붙이지 않는다.

 

이렇게 하면 의도대로 동작한다.

이런 간단한 예시에서는 괜찮지만 만약 props drilling이 너무 깊어진다면
Context API나 상태 관리 라이브러리를 사용하는 것이 좋다.

🔎 앵귤러와 뷰

React와 마찬가지로 단방향 바인딩만을 지원하는 Angular와 Vue에서

Angular는 [(ngModel)], Vue는 v-model을 사용해 양방향 데이터 바인딩처럼 동작하게 할 수 있다.

 

🟣 리덕스

Redux 또한 단방향 데이터 흐름을 사용한다.

store에서 모든 state를 관리하고 있고, action을 dispatch해야 reducer가 state를 업데이트할 수 있다.

그 후 해당 state를 구독하는 컴포넌트들이 선택적으로 리렌더링 된다.

 

Flux pattern

 

Reference>

  • https://sandroroth.com/blog/react-two-way-data-binding
  • https://velog.io/@kimju0913/단방향-바인딩과-양방향-바인딩
  • https://velopert.com/1225
  • https://ui.toast.com/weekly-pick/ko_20151027

 

    'React' 카테고리의 다른 글
    • [Next.js] 원티드 프리온보딩 FE 챌린지 10월 사전과제
    • [React] 컴포넌트의 생명주기(Lifecycle)
    • [React] CRA에서 모듈 import 시 절대경로 사용하기
    윤휴먼
    윤휴먼
    프론트엔드 개발자 준비 중. 디테일과 조화를 좋아합니다. ISFP😊

    티스토리툴바