HTML 폼 엘리먼트는 폼 엘리먼트 자체가 내부 상태를 가지기 때문에, React의 다른 DOM 엘리먼트와 다르게 동작한다.
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>
엘리먼트는 텍스트를 자식으로 정의한다.<textarea>
는 value 어트리뷰트를 대신 사용한다.<select>
는 드롭 다운 목록을 만든다.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
종종 동일한 데이터에 대한 변경사항을 여러 컴포넌트에 반영해야 할 필요가 있다.
이럴 때는 가장 가까운 공통 조상으로 state를 끌어올리는 것이 좋다.
props는 읽기 전용이다!
React는 강력한 합성 모델을 가지고 있으며, 상속 대신 합성을 사용하여 컴포넌트 간에 코드를 재사용하는 것이 좋다.
이러한 컴포넌트에서는 특수한 children prop을 사용하여 자식 엘리먼트를 출력에 그대로 전달하는 것이 좋다.
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
props와 합성은 명시적이고 안전한 방법으로 컴포넌트의 모양과 동작을 커스터마이징하는데 필요한 모든 유연성을 제공한다.
React는 JavaScript로 규모가 크고 빠른 웹 애플리케이션을 만드는 가장 좋은 방법이다.
React의 가장 멋진 점 중 하나는 앱을 설계하는 방식이다.
모든 컴포넌트(와 하위 컴포넌트)의 주변에 박스를 그리고 -> 그 각각에 이름을 붙기
디자이너의 Photoshop 레이어 이름이 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))는 모든 것을 모듈화 하고 빠르게 만들어준다.
UI를 상호작용하게 만들려면 기반 데이터 모델을 변경할 수 있는 방법이 있어야 한다. 이를 React는 state를 통해 변경한다.
애플리케이션을 올바르게 만들기 위해서는 애플리케이션에서 필요로 하는 변경 가능한 state의 최소 집합
을 생각해보아야 한다.
여기서 핵심은 중복배제원칙
이다. 애플리케이션이 필요로 하는 가장 최소한의 state
를 찾고 이를 통해 나머지 모든 것들이 필요에 따라 그때그때 계산되도록 만들기.
예를 들어 TODO 리스트를 만든다고 하면, TODO 아이템을 저장하는 배열만 유지하고 TODO 아이템의 개수를 표현하는 state를 별도로 만들지 않기!
TODO 갯수를 렌더링해야한다면 TODO 아이템 배열의 길이를 가져오면 된다.
어떤 게 state 가 되어야 하지 ??
어떤 컴포넌트가 state를 변경하거나 소유할지 찾아야 한다!
React는 항상 컴포넌트 계층구조를 따라 아래로 내려가는 단방향 데이터 흐름을 따른다!!
TIP!!
React는 전통적인 양방향 데이터 바인딩(two-way data binding)과 비교하면 더 많은 타이핑을 필요로 하지만 데이터 흐름을 명시적으로 보이게 만들어서 프로그램이 어떻게 동작하는지 파악할 수 있게 도와준다.
코드를 쓸 일보다 읽을 일이 더 많다는 사실을 기억하자
모듈화되고 명시적인 코드는 읽을 때 조금 덜 어렵다.
큰 컴포넌트 라이브러리를 만들게 되면 이 명시성과 모듈성에 감사할 것이며 코드 재사용성을 통해 코드 라인이 줄어들기 시작할 것이다!. :)
reference
React Form Libraries comparison: Formik vs React Hook Form