React State & Props

yeon·2022년 10월 3일
0

FE

목록 보기
8/15

💡 진행하면서 느꼈던 점

리액트 기초를 배울 때까지는 익숙하지 않아서 그렇지 어찌저찌 코드를 짜면서 이해는 되었는데, State를 학습하면서 나 자신의 이해력에 대한 의구심이 들기 시작했다,,^^ Props는 그냥 상속이라고 생각하니 크게 어렵지 않았지만 State가 정말 큰 복병이었다. 큰 틀이나 문법이 뭘 말하고 있고, 어떤 개념인 건지는 대강 알겠는데 막상 응용 과제 코드를 작성하려니까 State의 세세한 부분까지 온전히 이해하지 못해서 막막했고, 이 코드는 왜 실행 되지/안 되지?의 연속이었다. 일단 머리에 다 넣다보면 어떻게든 이해가 되겠지.. 하면서 진행하고 있기는 한데, State가 중요한 개념이다보니 어물쩡 넘어가서는 안 될 것 같고 모르는 부분은 계속해서 구글링하고 완전히 이해가 될 때까지 빡세게 부딪혀 봐야겠다.

🚩 새롭게 알게 된 것

Props

props는 컴포넌트의 속성(property)를 의미한다. props는 State와 달리 변하지 않는, 외부(부모 컴포넌트, 상위 컴포넌트)로부터 전달받은 값이다.

React 컴포넌트는 Jacvascript 함수와 클래스로 props를 함수의 전달 인자처럼 전달받아 화면에 어떻게 표시되는지를 기술하는 React 엘리먼트를 반환한다.(참고로 props는 클래스 컴포넌트와 함수형 컴포넌트 모두에서 사용할 수 있다.) 따라서 이 엘리먼트를 컴포넌트가 최초 렌더링될 때 화면에 출력하고자 하는 데이터를 담은 초깃값으로 사용이 가능하다.

props는 어떤 타입의 값도 넣어 전달할 수 있도록 객체 형태를 가진다. 속성의 이름은 임의로 지정해줄 수 있다. 객체의 {key:value}는 상위 컴포넌트에서 정의한 {attribute:value}의 형태를 띠게 된다. 따라서 Javascript의 객체의 value에 접근할 때 dot notation을 사용하는 것과 마찬가지로 props의 value 또한 dot notation으로 접근이 가능하다.

props는 외부로부터 전달받아 변하지 않는 값이므로 함부로 변경될 수 없는 읽기 전용(read-only) 객체이다. props를 전달받은 하위 컴포넌트 내에서 props를 직접 수정할 경우 상위 컴포넌트 값에 영향을 미치게 되고, 의도하지 않은 side effect가 발생한다. 또한 이는 React의 단방향, 하향식 데이터 흐름 원칙(React is all about one-way data flow down the component hierarchy)에 위배된다.

How to use props

1. 하위 컴포넌트에 전달하고자 하는 속성과 값을 상위 컴포넌트에 정의한다.

<컴포넌트 이름 attribute={value}>
// ex) <Child text={"I'm text"}>

2. props를 이용하여 하위 컴포넌트에 정의된 속성과 값을 전달한다.
(하위 컴포넌트 전달 인자에 props{attribute}를 넣어야 한다)

3. 전달받은 props를 하위 컴포넌트에서 렌더링한다.

{props.attribute}
{props.children} // 상위 컴포넌트 <Child>I'm text</Child>

+ props 변수에 값을 할당하고 spread syntax 이용하여 전달하는 방법

function Parent() {
	const props = {
    	attribute: "value"
    };
  	return <Child {...props} />;
}

State

state는 컴포넌트 내부에서 변할 수 있는 값이다. props와 다르게 외부의 영향을 받지 않는다. 부모로부터 props를 통해 전달받지 않고, 변화하는 값이며 컴포넌트 안의 다른 state나 props를 가지고 계산이 가능하지 않아야 한다. 관련 기능으로는 Toggle Switch, Counter, Checkbox 등이 있다.

useState

1. React로부터 useState 불러오기

import {useState} from "react"

2. useState를 컴포넌트 안에서 호출해주기

const [state 저장 변수, state 갱신 함수] = useState(상태 초기값)

useState를 호출한다는 것은 "state"라는 변수를 선언하는 것과 같고, 변수의 이름은 임의로 지어도 된다. 일반적인 변수는 함수가 끝나면 사라지지만, state 변수는 React에 의해 함수가 끝나도 사라지지 않는다.

useState를 호출하면 배열을 반환하는데, 반환되는 배열의 0번째 요소는 현재 state 변수이고, 1번째 요소는 이 변수를 갱신할 수 있는 함수이다. useState의 인자로 넘겨주는 값은 state의 초깃값이다. 즉, useState의 전달인자는 useState가 반환하는 배열의 첫 번째 요소에 넘겨주는 초기 상태 값이다.

3. state 변수에 저장된 값을 사용하려면 JSX 엘리먼트에 직접 불러서 사용

// 사용 예시
<span>{state 저장 변수 ? "true state text" : "false state text"}<span>

4. state 갱신하기

state를 갱신하려면 (위 2단계에서 배열 안의)state 갱신 함수를 호출해야 한다.

브라우저에서 특정 값이 변경된다면 React의 state 저장 변수도 변경되게 해야 한다. 이는 (1) 변경되는 태그 안의 속성에 state 저장 변수를 값으로 할당하여 반영할 수 있다.
input이나 button 등의 엘리먼트 값이 변경되면(사용자가 입력하거나 클릭해서 값을 변경하면) onChange 이벤트가 발생하는데, (2) onChange 속성의 값에 이벤트 핸들러 함수를 호출하고, (3) 이 이벤트 함수가 state 갱신 함수를 호출하게 한다. 이렇게 하면 React는 새로운 state 저장 변수를 컴포넌트에 넘겨 다시 렌더링하게 된다.

React 컴포넌트는 state가 변경되면(상태가 변경될 때마다) 새롭게 호출되고 리렌더링된다. 또한 React state는 state 갱신 함수 호출로 변경해야 한다. 강제로 변경을 시도하면 리렌더링이 되지 않거나 state가 제대로 변경되지 않는다.

이벤트 처리

React에서 이벤트는 소문자 대신 camelCase를 사용한다. ex) onClick={}

onChange

<input>, <textarea>, <select>와 같은 Form 엘리먼트는 사용자의 입력값을 제어하는 데 사용된다. React에서는 변경될 수 있는 입력값을 컴포넌트의 state로 관리하고 업데이트한다.

onChange<input>의 텍스트가 바뀔 때마다 발생하는 이벤트인데, onChange 이벤트가 발생하면 인자명.target.value를 통해 이벤트 객체에 담겨 있는 <input> 값을 읽어올 수 있다. 따라서 <input> 태그 안 onChange 속성에 대한 값으로 이벤트 핸들러 함수를 할당하고, 이벤트 핸들러 함수 안에는 state 갱신 함수를 내용으로 하면서 인자 안에 이벤트 핸들러 인자명.target.value를 넣는다. 이렇게 작성하면 이벤트 발생 시 이벤트 핸들러 함수가 작동하면서 이벤트 객체를 반환하고, 이벤트 객체에 담긴 <input> 값을 state 갱신 함수를 통해 새로운 state로 갱신할 수 있다.

onClick

onClick 이벤트는 사용자가 클릭했을 때 발생하는 이벤트이다. 버튼이나 <a> 태그를 통한 링크 이동 등 주로 사용자 행동에 따라 애플리케이션이 반응해야 할 때 자주 사용하는 이벤트이다.

onClick 속성에 대한 값에 함수를 괄호와 함께 바로 호출하면, 컴포넌트가 렌더링될 때 함수 자체가 아닌 함수 호출의 결과가 onClick 속성에 적용된다. 이렇게 되면 버튼을 클릭할 때가 아닌, 컴포넌트가 렌더링될 때에 함수가 실행되고, 그 결과인 undefined(함수는 리턴값이 없을 때 undefined를 반환하므로)가 onClick에 적용되어 클릭했을 때 아무런 결과도 일어나지 않는다.

따라서 리턴문 외부에 함수를 정의한 후 이벤트 핸들러 함수에 함수 자체를 값으로 할당해주거나, 리턴문 안에서 함수를 정의해야 한다.

⭕️ {이벤트 핸들러 함수}
⭕️ {() => state 갱신 함수(내용)}

{이벤트 핸들러 함수()} → 함수를 바로 호출할 경우 컴포넌트가 렌더링 될 때 함수 호출의 결과가 onClick에 적용된다. 때문에 사용자가 입력을 할 때가 아닌, 컴포넌트가 렌더링 될 때 이벤트 핸들러 함수가 실행되기 때문에 무한으로 페이지가 렌더링되게 된다.
{() => 이벤트 핸들러 함수} → 이벤트 핸들러 함수가 리턴될 뿐, 호출되지는 않는다.

React 데이터 흐름

React 개발 방식의 가장 큰 특징은 페이지 단위가 아닌, 컴포넌트 단위로 시작한다는 점이다.

  • 상향식(bottom-up) 앱 제작
    페이지를 만들기 이전에, 컴포넌트를 먼저 만들고 조립한다. → 테스트가 쉽고 확장성이 좋다.

  • 하향식(top-down) 데이터 흐름
    컴포넌트 바깥에서 props를 이용해 데이터를 마치 인자나 속성처럼 전달받을 수 있다. 데이터를 전달하는 주체는 부모 컴포넌트가 된다.

  • React는 단방향 데이터 흐름(One-way-data flow)를 따른다

  • 단일 책임 원칙에 따른 구분
    하나의 컴포넌트는 한 가지 일만 한다.

  • state는 최소화
    모든 데이터를 state로 둘 필요는 없다. state가 많아질수록 애플리케이션은 복잡해지므로, 최소화하는 것이 가장 좋다.

  • 하나의 state를 기반으로 두 컴포넌트가 영향을 받는다면, 공통 소유 컴포넌트(두 자식의 공통 부모 컴포넌트)를 찾아 그곳에 state를 위치해야 한다.


🔥 추가 학습이 필요한 것

  • 태그의 속성 내용을 임의로 작성할 수 있다고 했는데, 그럼 임의로 작성된 속성에 state 저장 변수를 할당하면, 그 속성이 뭔지 알고 바로 그 속성에 변하는 상태인 것으로 알아듣고 state 변수를 갱신해주는 것인지 원리를 모르겠다.

  • 이벤트 객체.target.value의 value와 <input value={state 저장 변수}>의 value는 같은 것인지, 다른 것인지 모르겠다. props의 속성은 임의로 작성할 수 있다고 했는데, state에도 적용이 되는 것일까? 안 되는 것일까? 만약 둘이 같은 것이라면, state 갱신 함수가 어떻게 작동하여 state 저장 변수의 값을 갱신하는 것인지 원리가 이해가 가지 않는다.
    관련 참고 링크

    ➡️ 이벤트 객체에는 발생한 이벤트에 대한 모든 정보가 담겨 있다. 그 중 target 속성에는 이벤트가 발생한 엘리먼트에 대한 정보가 담겨 있다. 그래서 target.value에서 선택된 옵션의 값을 확인할 수 있다. 즉, state 갱신 함수가 호출되어 state 저장 변수의 값이 바뀌게 되면 React는 페이지를 렌더링하고 리턴되는 태그의 내용이 event.target.value의 값으로 리렌더링되어 바뀐다.

    ➡️ React Blackbox와 관련있는데, React에서 관리하는 것이라 이름이 value로 같아도 까보면 완전히 다르다. 순환참조라고 볼 수 없다. 원시 자료형끼리는 순환 참조가 없음.

  • 렌더링 원리 관련 링크

  • useState를 이용해 Toggle Popup 페이지를 구현했을 때 state 저장 변수의 값이 true인지 false인지에 따라 팝업창이 뜨는 방식으로 작동하는데, 버튼 태그의 onClick 속성의 값에 state 저장 변수의 true/false 값을 바꿔주는 state 갱신 함수를 넣고, return문 안에 삼항연산자를 넣는다고 팝업 창이 어떻게 뜨는 것인지 납득이 가지 않는다. 팝업창이 뜨는 게 아니라 그냥 버튼 아래에 내용이 나올 수도 있는 것 아닌가?? 팝업 관련 태그 없이 div태그만으로 어떻게 가능한건지 모르겠다. 또 삼항 연산자에서 state 저장 변수가 false일 경우 null인 이유도 이해하고 싶다. 제발 이해하게 해줘....

  • React의 단방향 데이터 흐름(One-way data flow)

  • click-to-edit ui

  • local state

  • React에 존재하는 다양한 Hook들

0개의 댓글