> pnpm add -D tailwindcss postcss autoprefixer
> pnpm tailwindcss init -p
조건
- 순수 함수는 주어진 처리만 진행해야 한다.
- 호출되기 전에 존재했던 객체, 변수는 변경하지 않아야 한다.
- 동일 입력, 동일 출력.
- 동일한 입력이 주어지면 순수 함수는 항상 동일한 결과를 반환해야 한다.
사이드 이펙트
리액트에서의 컴포넌트는 JSX를 반환하고 외부 상태를 변경해서는 안된다.
React가 순수함을 중요하게 생각하는 이유
1. 컴포넌트는 다른 환경(예: 서버)에서 실행될 수 있다. 동일한 입력에 대해 동일한 결과를 반환하므로 하나의 컴포넌트가 많은 사용자 요청을 처리할 수 있다.
2. 입력이 변경되지 않은 렌더링일 경우, 렌더링을 건너 뛰어 성능을 향상시킨다. 순수 함수는 항상 동일한 결과를 반환하므로 캐시하기에 안전하다.
3. 컴포넌트의 깊은 트리를 렌더링하는 도중 일부 데이터가 변경되면 React는 오래된 렌더링을 완료하는데 시간을 낭비하지 않고 렌더링을 다시 시작할 수 있다. 순수함을 유지하면 언제든지 계산을 중단해도 안전하다.
컴포넌트 순수성 유지
1. 컴포넌트 렌더링 단계에 영향을 미치지 않도록 순수함을 유지해야 한다.
2. 사이드 이펙트(부수 효과)를 유발하는 코드를 함수 몸체(body)에 작성해서는 안된다.
3. 동일 입력 동일 출력을 지키자 (props읽기 전용 => JSX 반환)
4. Strict Mode 컴포넌트의 역할은 계산이 순수한지 확인하는 것.(2번 렌더링. 즉 계산이 여러번 되더라도 입출력이 동일해야 한다.)
5. Strict Mode는 배포(production) 모드에서 제거되므로 성능에 영향을 주지 않는다.
6. 로컬 뮤테이션은 컴포넌트 함수 내부에서 이뤄져도 문제가 되지 않는다.
기존 값을 변경하는 것을 뮤테이션(mutation)이라 한다.
순수 함수는 함수 범위 밖의 변수나 호출 전에 생성된 객체를 변경하지 않는다.
내부적으로만 수정하게 되면 컴포넌트 외부에서는 어떤 일이 발생했음을 알 수 없다.
이처럼 컴포넌트 내부적으로만 생성, 수정이 이뤄지는 것을 “로컬 뮤테이션”이라고하고
컴포넌트 함수 내부의 것을 변경 (로컬 뮤테이션)하는 것은 가능하다.
변경 사항(화면 업데이트, 애니메이션 시작, 데이터 변경)을 사이드 이펙트라고 한다.
렌더링 하는 동안이 아니라, “외부에서 발생하는 부수적인 일들”을 말한다.
함수형 프로그래밍은 순수 함수에 크게 의존하지만 어느 시점, 위치에서는 무언가 변경되어야한다.
React에서 사이드 이펙트는 일반적으로 이벤트 핸들러,
이벤트 핸들러는 컴포넌트 내부에 정의되어 있지만, 렌더링 중에는 실행되지 않는다.
따라서 이벤트 핸들러는 순수할 필요가 없다.
사이드 이펙트
1. 렌더링 단계(렌더 트리거 => 컴포넌트 렌더링 => DOM 커밋) 중 DOM 커밋 시점에 실행(콜백)되는 로직에서는 사이드 이펙트 처리 가능
2. 사이드 이펙트는 DOM 커밋 이후에 실행 되어야 한다. (접근성, 요서의 스타일 변경 등 모든 명령형 프로그래밍 코드)
3. 사이드 이펙트 코드 로직을 허용하는 영역은 2가지 (이벤트 핸들러, useEffect 훅의 이펙트 콜백 함수)
사이드 이펙트를 처리할 이벤트 핸들러가 없을 경우, 컴포넌트 내부에서 useEffect 훅을 호출해 컴포넌트가 반환한 JSX에 연결할 수 있다.
useEffect 훅을 사용하면 사이드 이펙트가 필요한 렌더링 시점 이후 React에 의해 실행되지만 이러한 방법은 꼭 필요한 경우(DOM 접근 조작 등)에만 사용되어야 한다.
useEffect
내부에서는 순수하지 않아도 괜찮다. 그외의 즉, 컴포넌트 내부에서는 반드시 순수해야 한다.
네트워크 요청 및 응답은 사이드 이펙트를 처리할 이벤트 핸들러가 없다.즉,useEffect
를 사용 한다. (함수 몸체에서 선언하면 무조건 한번 실행된다.)
null이 나오는 이유?
=>렌더링 동안 컴포넌트 결과(JSX)가 ReactDOM이 렌더링(DOM 커밋)이 되기 전에 호출하기 때문
컴포넌트에서 조작할 수 있는, 변경 가능한 데이터
상태관리 라이브러리
import { sculptureList } from './data';
export default function Gallery() {
let index = 0;
function handleClick() {
index = index + 1;
}
let sculpture = sculptureList[index];
return (
<>
<button type="button" onClick={handleClick}>
다음
</button>
<h2>
{sculpture.artist}의 <i> {sculpture.name}</i>
</h2>
<h3>
({index + 1} / {sculptureList.length})
</h3>
<img
src={sculpture.url}
alt={sculpture.alt}
/>
<p>{sculpture.description}</p>
</>
);
}
화면이 변경되지 않는 이유는 다음과 같다.
새 데이터로 컴포넌트를 업데이트 하려면 다음의 2가지가 필요하다.
useState 훅(hook)은 다음의 2가지를 제공한다.
const [index, setIndex] = useState(0);
컴포넌트 안에서 useState 훅 함수를 호출하면 무언가 기억하기를 원한다고 React에게 알리는 것
useState() 함수에 전달된 0은 기억해야 할 값의 초깃값,훅 함수가 호출되면 배열을 반환
반환된 배열의 첫번째 순서는 반드시 상태(state)가 자리하고, 두번째는 반드시 상태를 업데이트 하는 상태 업데이트 함수가 자리
그러므로 구조 분해 할당 구문을 사용해 상태와 상태 업데이트 함수를 추출할 수 있다.
useState()
함수에 설정된 0
이 최초의 index
값으로 설정.setIndex(index + 1)
실행으로 React에 상태 업데이트를 요청.setIndex()
함수 실행으로 함수 컴포넌트를 다시 실행시킨다. 내부에서 useState 훅 함수를 만나면 setIndex()
함수에서 전달받은 새로운 상태 값을 계산해(0
→ 1
) index
값으로 설정한다.React가 제공하는 “use”로 시작하는 함수는 모두 훅(hooks)이라고 불린다.
훅은 React가 렌더링 되는 동안만 사용할 수 있는 “특별한 함수”이며 상태 관리 훅인 useState는 이러한 훅 함수 중 하나이다.
React 훅 함수는 컴포넌트 또는 use로 시작하는 다른 함수(커스텀 훅) 안에서만 사용 가능하며 최상위 수준에서만 호출할 수 있다. 조건 또는 반복문, 일반 함수 안에서 훅을 사용할 수 없음.
React 훅은 함수이지만, “컴포넌트의 요구사항에 대한 무조건적인 선언”으로 생각해도 좋다.
rendering trigger를 발생시키려면??
"상태 = 독립적인 비공개 데이터"
상태는 화면의 컴포넌트 인스턴스에 대한 지역 변수.
즉, 동일한 컴포넌트가 여러 번 렌더링 되더라도 각 인스턴스가 완전히 격리된 상태다. 둘 중 하나를 변경해도 다른 하나는 영향을 받지 않는다.
이것이 상태 변수가 일반 변수와 다른 점, 상태 변수는 특정 함수 호출이나 코드의 위치에 연결되지 않지만, 화면의 특정 위치에서 “지역 변수”가 된다.
상태는 그것을 선언한 컴포넌트 내부에서 사용 가능하며 완전히 비공개 데이터이며 상위 컴포넌트에서는 접근 및 조작할 수 없다.
이렇게 하면 나머지 컴포넌트에 영향을 주지 않고 컴포넌트에서 상태를 추가하거나 제거할 수 있다.
2개 이상의 컴포넌트에서 상태를 동기화 된 상태로 유지하려면
하위(자식) 컴포넌트에서 상태를 제거하고, 컴포넌트들을 공유하는 가장 가까운 상위(부모) 컴포넌트로 상태를 끌어올려 관리해야한다.
vscode에서 절대경로 설정하기
// jsconfig.json { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["src/*"] } } }
각각의 상태를 관리해 버튼이 각자 움직도록 만들기
컴포넌트 상태 관리
1. JavaScript 로컬 변수를 사용하면 React 컴포넌트의 상태를 관리할 수 없다.
2. React가 제공하는 useState hook을 사용해야 상태 관리가 가능하다.
3. useState hook은 배열을 반환하는데 첫번째 항목은 상태, 두번째 항목은 상태 업데이트 함수다.
4. useState hook이 반환한 상태 업데이트 함수가 실행되면 React에게 렌더 트리거(render trigger)를 발생시킨다.
5. 렌더 트리거는 컴포넌트를 다시 실행시킨다. (리-렌더링 발생)
6. 일반 로컬 변수는 함수 재실행 과정에서 초기화되지만, useState에서 추출된 상태는 이전의 값을 기억한다.
7. 컴포넌트 내부에서 상태를 관리하는 것이 가능하다. useState 훅을 사용해 여러 상태를 관리할 수 있다.
8. 상태 업데이트 함수는 사용법이 2가지인데 하나는 다음 상태(nextState) 값을 직접 전달하는 것이고, 다른 하나는 set 함수를 사용하는 것이다.
9. set 함수를 사용한 업데이트는 이전 상태 값을 토대로 계산된 다음 상태 값을 반환해야 한다.