React Basics
React의 기초 개념들을 알아봅시다.
4.1 CSR (클라이언트 사이드 렌더링)
network에 가서 보면 localhost가 제일 먼저 download 된다는걸 알 수 있다
(bundle.js) → webpack은 application code와 react코드를 압축해서 하나의 파일로 만들어준다.
즉, 처음 browser가 전달받은 html 안에는 아무것도 없고 root 태그 하나만 있다.
client side rendering을 하기 때문에, 우리는 html를 보내주고 react코드를 함께 보내주면서 client side에서(browser에서) 동적으로 react code를 실행하며 요소를 생성한다.
root
/index.js
createRoot라는 API는 html에 있는 root라는 요소를 가져와서 (변수)root라는 가상의 요소를 만들어준다.
root에 첫번째 컴포넌트를 rendering한다. (여기서는 App)
App은 StrictMode로 만들어지는데, 개발시 엄격한 모드에서 개발할 수 있도록 하고 배포시에는 StrictMode가 알아서 꺼진다.
4.2 최신 yarn 설정
eslint와 yarn 충돌로 에러가 발생시 해결하는 법
- yarn을 종료한다
yarn add -D eslint-config-react-app
로 설치해준다.- root directory(최상위)에
.yarnrc.yml
파일을 만들어준다. - /.yarnrc.yml 에 아래의 내용 작성
- 이렇게 해도 여전히 에러가 발생한다면 yarn을 종료한 이후
yarn cache clean
을 한 다음yarn install
로 처음부터 setup한다.- 그렇다면 정상적으로 작동한다.
프로젝트 설치할 때마다 설정하기 번거롭다면…
4.3 JSX 문법 정리 ( 기본 )
규칙
- 함수이름은 항상
대문자
로 시작한다. - return 값은 항상 JSX로 반환해야 한다.
- props를 받을 수 있다
1. Component는 오직 1개의 태그만 반환해야 한다.
- JSX를 반환할 때 반환해야 하는 태그는 오직 1개만 가능하다.
- 여러개의 태그를 반환하고 싶다면, 부모 태그 하위에 자식태그를 넣어주어야 한다.
- 하지만 마냥 부모 태그(div)로 감싸고 싶은 경우가 아니라, 그저 다수의 태그를 넣고싶은 경우라면 를 넣어주면 된다. 혹은 이렇게 react 내부적으로 Fragment를 사용해도 된다. Fragment와 empty tag는 서로 동일한 역할을 한다.
2. class가 아닌 className을 사용한다.
3. JS 코드를 작성할 때는 를 사용해야 한다.
JS코드를 작성하거나 변수를 할당해서 넣을 때는 중괄호를 사용해야 한다.
즉 이 코드는 JS의 Object에 width와 height이라는 name을 주고 각각의 문자열을 할당해서 를 이용해 interpolation을 해준 것과 같다.
4.4 JSX 문법 정리 (심화)
1. 반복되는 태그는 피하고 JS 문법으로 활용하기
li 태그가 반복된다면 li 태그를 여러개 적어줄 필요 없이
Array에 넣어서 map을 이용해 태그의 반복이 가능하다.
위의 코드는 이와 같다.
4.5 컴포넌트 만드는 꿀팁
Tips
- component들의 확장자는 가급적
.jsx
혹은.tsx
로 명시해준다. - 가급적이면 src 폴더 하위에
components
folder를 만들어 components들을 저장한다.
Components 생성 및 export 하기
- component는 components 폴더 안에 생성
- component를 작성하면 꼭
export default
를 해준다.
요렇게 바로 export default를 적는걸 더 선호한다.
4.6 Props 사용하기
- 하드 코딩이 아닌 props를 이용해 데이터를 전달한다.
- 상위 component에서 props를 전달한다. 즉, 컴포넌트에서 속성의 key와 value를 명시하고 props라는 객체로 전달을 해주게 된다. 즉, 컴포넌트 내에서는 props. 으로 접근 가능한 것
구조분해할당 으로 props 설정하기
구조분해 할당을 이용해서 props 속성(key값)을 설정해주면
따로 props.name으로 접근할 필요 없이 바로 속성의 key로 할당이 가능하다.
4.7 Event 처리하기
event를 처리하고 싶다면 자바스크립트처럼 onClick을 넣어서 Event를 처리해줄 수 있다.
function()
을 넣어줄 수도 있고, 익명함수를 이용해 event처리도 가능하다.
그런 다음 console.log에 찍힌 event를 확인해보면
React에서는 SyntheticBaseEvent가 발생한다.
혹은
이렇게 외부에 함수를 정의해서 클릭해줘도 같은 역할을 한다.
4.8 내부 상태관리 State
아무리 Add+를 클릭해도 숫자가 증가하지 않는다. (비록 콘솔에는 1씩 증가하게 되더라도)
⇒ 즉 State
를 사용해야만 한다.
useState
값이 변경이 될때마다 UI를 업데이트 하기 위해서는 useState
를 사용해야 한다.
useState
를 사용할 때 초기값을 지정하면 배열이 return
된다.
count는 이미 const 변수로 할당 되었기 때문에 직접적으로 변경해서는 안된다.
따라서, setCount()라는 함수를 이용해서 count의 값을 변화시켜준다.
setCount는 react에서 제공해주는 setCount라는 함수를 호출 하는 것이다.
즉, setCount
를 이용하면 react에서 Counter
라는 전체 함수를 다시 호출해준다.
Counter가 다시 호출되면 반환되는 return에 현재 count값이 들어가므로 전체가 값이 업데이트 될 수 있다.
prop이 변경되거나, useState의 상태가 변경이 된다면 → 즉 setCount를 호출했을 때 useState와 같은 것들의 내부 상태가 변경이 된다면.
변경이 될 때 마다 해당하는 함수를 다시 호출한다. 다만 VirtualDOM을 사용하기 때문에 이전의 DOM요소와 지금의 DOM요소에서 변경된 부분만 update해준다.
함수가 계속 호출이 되어도, count가 0으로 초기화 되지 않는 이유는 useState hook은 여러번 호출이 되더라도 초기값 0이 아닌, 이전의 값을 기억한다. 따라서 바뀌지 않게 된다.
useState 사용시 유의할 점
setCount
를 5번 호출하면 어떻게 될까?
정답은 5번을 호출해도 Add + 에 5가 더해지는게 아니라 1이 더해진다.
즉, 한 번 더할때 5씩 더하고 싶다면 이렇게 callback을 불러서 더하면 된다.
- 리액트 공식문서 설명
Queueing a Series of State Updates
It is an uncommon use case, but if you would like to update the same state variable multiple times before the next render, instead of passing the next state value likesetNumber(number + 1)
, you can pass a function that calculates the next state based on the previous one in the queue, likesetNumber(n => n + 1)
. It is a way to tell React to “do something with the state value” instead of just replacing it. Here,n => n + 1
is called an updater function. When you pass it to a state setter:- React queues this function to be processed after all the other code in the event handler has run.
- During the next render, React goes through the queue and gives you the final updated state.
When you call
useState
during the next render, React goes through the queue. The previousnumber
state was0
, so that’s what React passes to the first updater function as then
argument. Then React takes the return value of your previous updater function and passes it to the next updater asn
, and so on: Here’s what this event handler tells React to do: setNumber(number + 5)
:number
is0
, sosetNumber(0 + 5)
. React adds “replace with5
” to its queue.setNumber(n => n + 1)
:n => n + 1
is an updater function. React adds that function to its queue.
- Comments
4.9 카운터 상태 끌어올리기
AppCounter
Counter
AppCounter
은 total click수를 나타내야 한다. Counter
은 개별의 컴포넌트로서 기능을 한다. 즉, 부모에서 자식 컴포넌트에 onClick이라는 이름으로 handleClick함수를 prop으로 넘겨 주었고, 자식 컴포넌트에서 Add 버튼을 누르면 setCount를 통해 자식컴포넌트의 state값이 1 증가하고, 또한 onClick props로 받은 함수 handleClick이 실행되어 부모 컴포넌트의 count state값도 1 증가하게 된다.
4.10 useEffect 생애주기
데이터를 가져오고 싶은데, fetch 코드를 이렇게 작성하면 무한로딩이 발생한다!
Why?
products를 초기화 한 이후에 → setProducts로 상태를 변경한다.
그렇다면 어떤일이 발생할까? 즉, Products() 전체가 다시 호출되는 일이 발생한다. (상태를 변경해주기 위해)
즉, 함수가 다시 호출되었기 때문에 fetch 또한 다시 호출이 된다.
즉, useEffect 안에서 네트워크 통신이 이뤄져야 한다.
⇒ 즉 useEffect
를 사용하게 된다면(dependency를 넣어주게 되면) 데이터를 두 번 받아오지 않게 된다. 즉, 딱 한번만 호출받고 싶다면 두번째 인자로 빈 배열을 전달해주게 된다면 아무런 dependency가 전달되지 않아 한번만 호출되고 만다.
⇒ useEffect의 첫번째
인자는 콜백함수
, 두번째
인자는 dependency
함수를 호출하고 난 뒤, 컴포넌트가 사라질 때 메모리를 정리해야 한다면? (혹은 socket을 닫을 때)
⇒ useEffect 안에서 콜백함수를 return 해주면 된다.
- Question : 왜 useEffect 사용 시, console.log가 두 번씩 호출되는걸까? 정확하게는 Products라는 컴포넌트가 mount될때, unmounted 될 때의 함수 호출 1번, mounted 될 때의 뜨끈한 데이터가 2번 나타난다. ⇒ 이유는 index.js에서 React.StrictMode를 사용하고 있기 때문이다. 제거하면 정상적으로 실행이 된다. StrictMode에서는 컴포넌트가 두번씩 렌더링 되기 때문에, 로그도 두번씩 나올 수 있다. 참조 Strict Mode – React https://github.com/facebook/react/issues/24502
4.11 useEffect 제대로 사용하기
react application을 개발할 때, 특정한 값이 변경 될 때 다시 네트워크 요청을 해야하는 경우가 있다. 어떻게 할까?
checkbox가 toggle 될 때 마다, 새로운 데이터를 fetching 하고 싶다.
그렇다면 input의 값을 기본적으로 false로 설정을 하고, onChange를 통해 콜백함수를 불러
input의 value값을 setChecked를 통해 관리를 한다.
setChecked가 바뀔때마다, 조건문을 걸어 받아오는 데이터를 다르게 설정해주고
즉 mount/unmount가 번갈아 일어나며 데이터를 가져오는 것을 완성할 수 있다.
4.12 고유한 key
리액트 내부에서 고유한 값을 지정을 해주어야 한다.
즉, map을 이용해서 자식요소를 만드는 경우에는 고유한 key값을 설정해줘야 한다.
e