심리스 - 리액트 공식문서 3일차 : form, state, 합성, 상속, React로 생각하기

Seuling·2022년 7월 22일
0

FE

목록 보기
38/42
post-thumbnail

HTML 폼 엘리먼트는 폼 엘리먼트 자체가 내부 상태를 가지기 때문에, React의 다른 DOM 엘리먼트와 다르게 동작한다.

제어 컴포넌트 (Controlled Component)

HTML에서 <input>, <textarea>, <select>와 같은 폼 엘리먼트는 일반적으로 사용자의 입력을 기반으로 자신의 state를 관리하고 업데이트한다.
React에서는 변경할 수 있는 state가 일반적으로 컴포넌트의 state 속성에 유지되며 setState()에 의해 업데이트된다.

React 컴포넌트는 폼에 발생하는 사용자 입력값을 제어한다.
이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 “제어 컴포넌트 (controlled component)“라고 한다.

value 어트리뷰트는 폼 엘리먼트에 설정되므로 표시되는 값은 항상 this.state.value가 되고 React state는 신뢰 가능한 단일 출처 (single source of truth)가 된다.

React state를 업데이트하기 위해 모든 키 입력에서 handleChange가 동작하기 때문에 사용자가 입력할 때 보여지는 값이 업데이트된다.

textarea 태그

  • HTML에서 <textarea> 엘리먼트는 텍스트를 자식으로 정의한다.
  • React에서 <textarea> 는 value 어트리뷰트를 대신 사용한다.

select 태그

  • HTML에서 <select>는 드롭 다운 목록을 만든다.
  • React에서는 selected 어트리뷰트를 사용하는 대신 최상단 select태그에 value 어트리뷰트를 사용한다.
    - 한 곳에서 업데이트만 하면되기 때문에 제어 컴포넌트에서 사용하기 더 편합니다.

select 태그에 multiple 옵션을 허용한다면 value 어트리뷰트에 배열을 전달할 수 있다!

<select multiple={true} value={['B', 'C']}>

다중 입력 제어하기

여러 input 엘리먼트를 제어해야할 때, 각 엘리먼트에 name 어트리뷰트를 추가하고 event.target.name 값을 통해 핸들러가 어떤 작업을 할 지 선택할 수 있게 해준다.

주어진 input 태그의 name에 일치하는 state를 업데이트하기 위해 ES6의 computed property name 구문을 사용하고 있다.

this.setState({
  [name]: value
});

완전한 해결책

유효성 검사, 방문한 필드 추적 및 폼 제출 처리와 같은 완벽한 해결을 원한다면 Formik이 대중적인 선택 중 하나이다.
그러나 Formik은 제어 컴포넌트 및 state 관리에 기초하기 때문에 배우는 걸 쉽게 생각하면 안된다!!

Formik vs React-hook-form 차이점 뭐가있지 ?
Formik

  • 유효성 검사, 방문한 필드 추적 및 양식 제출 처리를 포함한 완전한 솔루션을 원하는 경우
  • 제어된 구성 요소를 사용
    React Hook Form
  • 제어되지 않는 구성 요소
    - 제어되지 않는 구성 요소는 DOM에 소스를 유지하기 때문에 React와 Non-React 코드를 통합하는 것이 더 쉽다
  • 입력 구성 요소를 다른 구성 요소로부터 격리하고 단일 입력에 대한 양식을 다시 렌더링하는 것을 방지한다.
  • 불필요한 재 렌더링을 방지
  • 간단한 형식에 적합하며 종속성이 없다.

State 끌어올리기

종종 동일한 데이터에 대한 변경사항을 여러 컴포넌트에 반영해야 할 필요가 있다.
이럴 때는 가장 가까운 공통 조상으로 state를 끌어올리는 것이 좋다.

props는 읽기 전용이다!

  • state는 렌더링에 그 값을 필요로 하는 컴포넌트에 먼저 추가된다.
  • 그러고 나서 다른 컴포넌트도 역시 그 값이 필요하게 되면 그 값을 그들의 가장 가까운 공통 조상으로 끌어올리면 된다.
  • 다른 컴포넌트 간에 존재하는 state를 동기화시키려고 노력하는 대신 하향식 데이터 흐름에 기대는 걸 추천한다.

합성 vs 상속

React는 강력한 합성 모델을 가지고 있으며, 상속 대신 합성을 사용하여 컴포넌트 간에 코드를 재사용하는 것이 좋다.

컴포넌트에서 다른 컴포넌트를 담기

이러한 컴포넌트에서는 특수한 children prop을 사용하여 자식 엘리먼트를 출력에 그대로 전달하는 것이 좋다.

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}

상속

props와 합성은 명시적이고 안전한 방법으로 컴포넌트의 모양과 동작을 커스터마이징하는데 필요한 모든 유연성을 제공한다.

  • 컴포넌트가 원시 타입의 값, React 엘리먼트 혹은 함수 등 어떠한 props도 받을 수 있다는 것을 기억하자!
  • UI가 아닌 기능을 여러 컴포넌트에서 재사용하기를 원한다면, 별도의 JavaScript 모듈로 분리하는 것이 좋다.
  • 컴포넌트에서 해당 함수, 객체, 클래스 등을 상속받을 필요 없이 import 하여 사용할 수 있다.

React로 생각하기

React는 JavaScript로 규모가 크고 빠른 웹 애플리케이션을 만드는 가장 좋은 방법이다.

React의 가장 멋진 점 중 하나는 앱을 설계하는 방식이다.

1단계: UI를 컴포넌트 계층 구조로 나누기

모든 컴포넌트(와 하위 컴포넌트)의 주변에 박스를 그리고 -> 그 각각에 이름을 붙기
디자이너의 Photoshop 레이어 이름이 React 컴포넌트의 이름이 될 수 있다.

컴포넌트 기준 ?

  • 우리가 새로운 함수나 객체를 만들 때처럼 만들면 된다.
  • 단일 책임 원칙 : 하나의 컴포넌트는 한 가지 일을 하는게 이상적이라는 원칙 - 하나의 컴포넌트가 커지게 된다면 이는 보다 작은 하위 컴포넌트로 분리되어야 한다.
  • UI와 데이터 모델이 같은 인포메이션 아키텍처(information architecture)를 가지는 경향이 있기 때문이다.
    각 컴포넌트가 데이터 모델의 한 조각을 나타내도록 분리하기.

2단계: React로 정적인 버전 만들기

데이터 모델을 가지고 UI를 렌더링은 되지만 아무 동작도 없는 버전을 만들어보기
정적 버전을 만드는 것은 생각은 적게 필요하지만 타이핑은 많이 필요로 하고, 상호작용을 만드는 것은 생각은 많이 해야 하지만 타이핑은 적게 필요로 하기 때문!!

데이터 모델을 렌더링하는 앱의 정적 버전을 만들기 위해 다른 컴포넌트를 재사용하는 컴포넌트를 만들고 props 를 이용해 데이터를 전달해준다.
props는 부모가 자식에게 데이터를 넘겨줄 때 사용할 수 있는 방법이다.
정적 버전을 만들기 위해 state를 사용하지 않기.
state는 오직 상호작용을 위해, 즉 시간이 지남에 따라 데이터가 바뀌는 것에 사용한다.

앱을 만들 때 하향식(top-down)이나 상향식(bottom-up)으로 만들 수 있습니다. 다시 말해 계층 구조의 상층부에 있는 컴포넌트 (즉 FilterableProductTable부터 시작하는 것)부터 만들거나 하층부에 있는 컴포넌트 (ProductRow) 부터 만들 수도 있다.
간단한 예시에서는 보통 하향식으로 만드는 게 쉽지만 프로젝트가 커지면 상향식으로 만들고 테스트를 작성하면서 개발하기가 더 쉽다.

이 단계가 끝나면 데이터 렌더링을 위해 만들어진 재사용 가능한 컴포넌트들의 라이브러리를 가지게 된다.
현재는 앱의 정적 버전이기 때문에 컴포넌트는 render() 메서드만 가지고 있을 것이다.
계층구조의 최상단 컴포넌트 (FilterableProductTable)는 prop으로 데이터 모델을 받는다.
데이터 모델이 변경되면 ReactDOM.render()를 다시 호출해서 UI가 업데이트 된다.
UI가 어떻게 업데이트되고 어디에서 변경해야하는지 알 수 있다.
React의 단방향 데이터 흐름(one-way data flow) (또는 단방향 바인딩(one-way binding))는 모든 것을 모듈화 하고 빠르게 만들어준다.

3단계: UI state에 대한 최소한의 (하지만 완전한) 표현 찾아내기

UI를 상호작용하게 만들려면 기반 데이터 모델을 변경할 수 있는 방법이 있어야 한다. 이를 React는 state를 통해 변경한다.

애플리케이션을 올바르게 만들기 위해서는 애플리케이션에서 필요로 하는 변경 가능한 state의 최소 집합을 생각해보아야 한다.
여기서 핵심은 중복배제원칙이다. 애플리케이션이 필요로 하는 가장 최소한의 state를 찾고 이를 통해 나머지 모든 것들이 필요에 따라 그때그때 계산되도록 만들기.
예를 들어 TODO 리스트를 만든다고 하면, TODO 아이템을 저장하는 배열만 유지하고 TODO 아이템의 개수를 표현하는 state를 별도로 만들지 않기!
TODO 갯수를 렌더링해야한다면 TODO 아이템 배열의 길이를 가져오면 된다.

어떤 게 state 가 되어야 하지 ??

  1. 부모로부터 props를 통해 전달됩니까? 그러면 확실히 state가 아닙니다.
  2. 시간이 지나도 변하지 않나요? 그러면 확실히 state가 아닙니다.
  3. 컴포넌트 안의 다른 state나 props를 가지고 계산 가능한가요? 그렇다면 state가 아닙니다.

4단계: State가 어디에 있어야 할 지 찾기

어떤 컴포넌트가 state를 변경하거나 소유할지 찾아야 한다!
React는 항상 컴포넌트 계층구조를 따라 아래로 내려가는 단방향 데이터 흐름을 따른다!!
TIP!!

  • state를 기반으로 렌더링하는 모든 컴포넌트를 찾으세요.
  • 공통 소유 컴포넌트 (common owner component)를 찾으세요. (계층 구조 내에서 특정 state가 있어야 하는 모든 컴포넌트들의 상위에 있는 하나의 컴포넌트).
  • 공통 혹은 더 상위에 있는 컴포넌트가 state를 가져야 합니다.
  • state를 소유할 적절한 컴포넌트를 찾지 못하였다면, state를 소유하는 컴포넌트를 하나 만들어서 공통 소유 컴포넌트의 상위 계층에 추가하세요.

5단계: 역방향 데이터 흐름 추가하기

React는 전통적인 양방향 데이터 바인딩(two-way data binding)과 비교하면 더 많은 타이핑을 필요로 하지만 데이터 흐름을 명시적으로 보이게 만들어서 프로그램이 어떻게 동작하는지 파악할 수 있게 도와준다.

리액트를 사용하면 ???

코드를 쓸 일보다 읽을 일이 더 많다는 사실을 기억하자
모듈화되고 명시적인 코드는 읽을 때 조금 덜 어렵다.
큰 컴포넌트 라이브러리를 만들게 되면 이 명시성과 모듈성에 감사할 것이며 코드 재사용성을 통해 코드 라인이 줄어들기 시작할 것이다!. :)

reference
React Form Libraries comparison: Formik vs React Hook Form

profile
프론트엔드 개발자 항상 뭘 하고있는 슬링

0개의 댓글