- 토이 프로젝트
element.classList.toggle
을 해주면 클래스 명이 있으면 없애고, 없으면 추가해 준다. class 이름을 바꿔주고 CSS에서 선택자로 디자인을 다르게 먹여서 토글 이벤트를 만들어낼 때 유용하다.input
창의type="checkbox"
는 이벤트 발생 시 자동으로checked
라는 속성을 추가한다. 만약에 여기서 수동으로 토글 처리를 해주면 아무 이벤트도 일어나지 않는 것처럼 보일 수 있다.
- React 공식 문서
- React에서
use
로 시작하는 모든 것은 훅(Hook)이다. 훅은 React가 렌더링 중일 때에만 사용할 수 있는 특별한 함수다. - 훅은 컴포넌트의 최상위 수준 또는 커스텀 훅에서만 호출할 수 있다. 조건문, 반복문 또는 기타 중첩 함수 내부에서는 훅을 호출할 수 없다.
- 훅은 함수이지만 컴포넌트의 필요에 대한 무조건적인 선언이다(무슨 얘기인지 이해가 잘 안 된다...).
- 컴포넌트 내부의
state
는 완전히 독립적이다. 같은 컴포넌트를 여러 번 호출해도 각각의state
는 독립이고, 심지어 부모 컴포넌트에서도 자식 컴포넌트의state
를 변경할 수 없다. useState
훅을 이용해 생성한state
가setState
를 통해 변경될 시 리액트는 상태의 변화가 있는 컴포넌트를 리렌더링 한다. 즉,state
의 변경이 렌더링의 트리거가 되는 것이다.state
가 변경되면 상태 변경이 있는 컴포넌트가 반환하는 JSX를 DOM Tree와 비교해서 변경 사항을 반영해 준다. 이 과정을 리액트가 자동으로 처리해 준다.state
가 변경되더라도 해당 시점마다 화면을 재렌더링 하는 게 아니다. 아래 코드는 한 번 클릭할 때마다 1씩 증가된다.state
가0
일 때 클릭 이벤트가 일어나더라도0 + 1
,1 + 1
,2 + 1
처럼 순차적으로 계산되어 상태가 변경되는 게 아니라, 렌더링 시점을 기준으로0 + 1
,0 + 1
,0 + 1
이 세 번 호출된다. 그래서 결국 1만 증가된다.
import { useState } from 'react'; export default function Counter() { const [number, setNumber] = useState(0); return ( <> <h1>{number}</h1> <button onClick={() => { setNumber(number + 1); setNumber(number + 1); setNumber(number + 1); }}>+3</button> </> ) }
- 해당 값을 실제로 변경하고 싶다면 콜백 함수를
setNumber
의 인자로 넘겨주면 된다. 이를 업데이터 함수라고 하며, 업데이터 함수는 렌더링 중에 실행되기 때문에state
를 변경하면 안 되고 순수해야 한다.setNumger(number => number + 1);
- state는 분명 변수와는 다르고 값이 바뀌고 처리되는 프로세스가 상이하다.
state
는 변경 시 컴포넌트를 다시 랜더링 하고, 랜더링을 기준으로 값의 변화가 정해진다. setTimeout
을 걸어도 마찬가지다. 화면에 렌더링이 먼저 완료되더라도, 이벤트가 발생하는 시점의state
값이 스냅샷으로 관리되기 때문에, 변경되지 않은 원래의 값이setTimeout
딜레이 안에 적용된다.- React는 등록된 이벤트 핸들러의 모든 코드가 완료된 이후에 화면을 리렌더링 한다. 이는 너무 잦은
state
변화로 인해 화면 리렌더링이 많이 될수록 성능에 문제가 생길 수 있기 때문에, 이를 방지하는 방식이다. 이러한 동작을 Batching이라고도 한다. - 상태의 변경에 다른 리렌더링 필요 사항을 큐에 저장한다. 큐는 선입 선출이기 때문에 먼저 큐에 들어간 변경 사항이 먼저 반영된다.
- 참조형 데이터도
state
가 될 수 있다. 단,state
를 변경할 때 동일한 참조에 내부 프로퍼티 일부만 바꾸는 식으로 처리하는 게 아니라, 아예 새로운 참조형 데이터를 복제해서 변경해야 한다. React는state
가 가리키는 참조가 변경돼야 상태의 변경으로 인식할 수 있는데, 참조형 데이터는 내부의 일부 값이 바뀌어도 스택 메모리 주소는 변하지 않기 때문에다(가변적이기 때문이다). React의 모든state
는 불변으로 처리해야 한다. - 참조형
state
의 경우 얕은 복사로 처리하면 내부에 있는 참조형 값이 변경되지 않아state
가 제대로 업데이트되지 않을 수 있다. 가급적 깊은 복사를 위한 도구(lodash
,immer
)를 사용해 깊은 복사 후 처리하자. - 보편적인 React 최적화 전략은 이전
props
또는state
가 다음 것과 동일할 때 일을 건너뛰는 방식으로 처리된다. - 불필요한
state
가 있다면 업데이트하는 것을 잊어버려 버그가 발생하기 쉽다. 주의하자. - 때때로 두 컴포넌트의
state
가 항상 함께 변경되기를 원할 수 있다. 이를 위해서는 각 컴포넌트에서 state를 제거하고 가장 가까운 공통 부모 컴포넌트로 옮긴 후 props로 자식들에게 전달해야 한다. state
의 구조 결정 시 좋은 구조의 근거로 제시된 다섯 가지 원칙이다.state
는 '더 단순하게'가 아니라 '가능한 최대로 단순하게' 만들어야 한다.- 연관된 state 그룹화하기: 두 개 이상의 state 변수를 항상 동시에 업데이트한다면, 단일 state 변수로 병합하는 것을 고려하세요.
- State의 모순 피하기: 여러 state 조각이 서로 모순되고 “불일치”할 수 있는 방식으로 state를 구성하는 것은 실수가 발생할 여지를 만듭니다. 이를 피하세요.
- 불필요한 state 피하기: 렌더링 중에 컴포넌트의 props나 기존 state 변수에서 일부 정보를 계산할 수 있다면, 컴포넌트의 state에 해당 정보를 넣지 않아야 합니다.
- State의 중복 피하기: 여러 상태 변수 간 또는 중첩된 객체 내에서 동일한 데이터가 중복될 경우 동기화를 유지하기가 어렵습니다. 가능하다면 중복을 줄이세요.
- 깊게 중첩된 state 피하기: 깊게 계층화된 state는 업데이트하기 쉽지 않습니다. 가능하면 state를 평탄한 방식으로 구성하는 것이 좋습니다.
- React는 UI 트리에서의 위치에 관심이 있다. UI 트리의 같은 위치에 등록되는 컴포넌트라면 설령 컴포넌트 내부에서 조건에 따라 JSX 리턴 값을 다르게 했더라도 React는 둘을 같은 컴포넌트로 인식한다. UI 트리 상에서의 위치가 같기 때문이다.
- 때문에, React는 컴포넌트가 같은 위치를 유지하면
state
를 유지한다.
- React에서
- 인프런 <한 입 크기로 잘라먹는 리액트>
props
는 부모 컴포넌트에서 자식 컴포넌트로 내려주는 데이터다. 기본적으로프로퍼티명="값"
형태로 사용되며, 내려갈 땐{ 프로퍼티 명: 값 }
처럼 객체 형태의 데이터가 내려간다.props
는 객체이기 때문에 자식 컴포넌트에서 구조 분해 할당으로 필요한 프로퍼티를 직접 가져올 수 있고, 부모 컴포넌트에서 전달할 때 스프레드 연산자(...
)를 사용하는 것도 가능하다.- 자식 컴포넌트에
컴포넌트.defaultProps
를 지정해 주면props
로 내려오는 값들의default
값을 지정해줄 수 있다.props
가 객체의 형태로 내려오기 때문에,defaultProps
도 객체로 지정해주면 된다. - 부모 컴포넌트에서 자식 컴포넌트를 만들 때 닫는 태그로 닫고(e.g.
<Button></Button>
) 그 사이에 값을 넣어주면 자식 컴포넌트에는children
프로퍼티로 값이 내려간다. - 컴포넌트에 이벤트 핸들러를 붙일 땐 컴포넌트의 리턴 JSX 구문 안에서 이벤트가 필요한 위치의 태그에 이벤트를 붙여주면 된다. 예를 들면
onClick
과 같은 형식이다. 이는 자바스크립트로 이벤트를 처리할 때 HTML 요소를getElementBy
나querySelector
를 사용해 선택하고 해당 요소에 이벤트를 달아주던 방식과 유사하다. - 이벤트로
onClick
을 사용했다면, 뒤에는={콜백 함수}
가 와야한다. 콜백 함수는 해당 위치에서() => {}
와 같이 화살표 함수로 바로 선언해줄수도 있고, 아니면 별도로 지정한 함수를 함수명으로 가져와 사용할 수도 있다. useState
는state
와 해당state
를 업데이트 해주는 함수를 반환한다.useState
의 인자로 값을 넘기면state
의 초기값이 지정된다.state
를 업데이트 해주는 함수는 값이 업데이트 될 시return
부분을 리렌더링 해주는 역할을 수행한다.useState
로 생성한state
가 갖는 특별함은state
의 값을 변경해주는setState
가 호출되면 화면이 다시 렌더링된다는 것이다. 이를 통해 상태를 통한 동적인 화면 전환을 구현하는 게 가능하다.- 리액트가 리렌더링 되는 조건은 컴포넌트 자신이 보유한
state
가 변하거나, 상위 컴포넌트로부터 받은props
가 변하거나, 부모 컴포넌트가 리렌더링되거나, 이렇게 세 가지다.
- HTML
select
태그- 드롭다운 메뉴로 선택지를 만들고 선택하게 하기 위해선 HTML의
<select>
태그를 사용하면 된다. <select>
태그의 하위에<option>
태그들로 드롭다운 메뉴의 항목들을 넣어주면 UI에 바로 반영된다.- 유저들에겐 선택지에 대한 설명을 친절하게 하기 위해 길고 명확한 텍스트를 사용해야 할 수 있다. 하지만, 해당
value
를 그대로 받아와 프로그래밍에서 사용하면 효율이 떨어질 수 있다. 그럴 경우,<option>
태그의value
속성의 값을 지정해주면 지정된 값을 미리 정해둔 값으로 받아와 사용할 수 있다. - 예를 들어,
<option value="kr">한국</option>
이라고 사용하면 '한국'이라는 선택지를 선택할 경우e.target.value
는kr
로 들어온다.
- 드롭다운 메뉴로 선택지를 만들고 선택하게 하기 위해선 HTML의
'TIL' 카테고리의 다른 글
241116 TIL (0) | 2024.11.17 |
---|---|
241114 TIL (10) | 2024.11.15 |
241112 TIL (3) | 2024.11.13 |
241109 TIL (1) | 2024.11.10 |
241108 TIL (2) | 2024.11.09 |