본문 바로가기

Web/React

[React] React 기초

React

1. 사용자 경험

2. Component의 재사용( 유지 / 보수)

3. 데이터-화면 일치

( 기존 웹개발은 직접 DOM에 접근하여 값을 변경하였지만 React의 경우 state로 값을 변경)

 

 

★ Webpack: 수백 수천개의 관련 파일들을 하나로 합쳐주는 것

 

 

★ Webpack에서 필요 없는 plugin을 추려 낼 때 하나씩 빼며 오류가 있는지 확인하며 하는 방법도 있음

 

 

Babel : 최신식 코드를 실제로 Javascript가 이해 할 수 있도록 바꾸어주는 library

 

 

★ babel

 - babel/core: 파일들을 최신 문법으로

 - babel/preset-env: 내가 원하는 환경대로 설정

 - babel/preset-react: react jsx를 사용할수있음

 - babel-loader: webpack과 babel을 연결

 

 

JS 부분과 JSX 부분을 섞어서 coding하지 말고 Method로 빼서 Refactoring을 해라

 

 

<form>에서는 onSubmit, <input> typesubmit 사용

 

 

★ input tag에서 value와 onchange attribute는 세트로 쓰임, 같이 쓰지 않으려면 defaultValue 선언

 

 

★ 함수에서는 useRef, 클래스에서는 createRef를 사용하여 ref 동작 사용 가능( window 객체에 정의되어 있는 함수사용을 원할때, input 에 focus를 주는 동작, DOM을 직접 관리해야 할 때)

 

 

React class에서 <input>focus를 주고 싶은 경우는 ref attribute를 추가

   input;

 

   <input ref={(c) => { this.input = c; }} />  

  

   this.input.focus();  --> input DOM 선택, 사용하고자 하는 함수에 추가

 

 

 Hooks에서 ref useRef로 선언 후 사용

   const inputRef = useRef(null);

 

   <input ref={inputRef} />   

 

   inputRef.current.focus();

 

 

★ const timeout = useRef(null); 과 같이 Ref를 사용하고 불러와야 할 경우 timeout.current와 같이 current를 사용하여 값을 불러옴

 

 

★ 값이 변화되는 부분은 state를 사용

 

CLASS

★ 객체안의 배열, 배열안에 객체의 복잡한 데이터구조인 경우는 PureComponent를 사용하여도 최적화가 어렵기 때문에 component를 여러개로 나누어 props를 단순히 만들면 문제 해결 가능

 

 

 class에서 setState 사용시 이전 값을 참조하는 경우에는 callback 함수를 만들어서 선언. setState 함수가 비동기이기때문에 여   러개의 setState 함수 사용시 문제가 될 여지가 있음, setState를 연달아 사용시 비동기 문제로 어떤 값이 들어올지 모름

  ex) this.setState((prevState) => ({ value: prevState.value + 1}))   

 

 

★ setState를 사용하는데 어디에서 사용해야할지 모르는 경우 componentDidMount()에서 사용하면 유용, render 안에서 사용 할 경우 무한 루프에 빠짐

 

 

 this.setState를 실행 할 경우 render가 일어남. this.setState() 함수를 render안에서 inline으로 선언하면 render 할 때마다 함수를 실행하기 때문에 자원낭비가 되므로 method로 빼야함

   

 

class에서 props를 contructor로 받을 경우 이점은 정밀한 동작, 기본 객체로는 안되는 동작을 할 수 있음, 예를 들어 props를 받아 filter나 기타 동작 후 state에 넣어주어야 할 경우

 

 

calss component에서 re-render를 원치 않는 함수는 render 바깥쪽에 선언

 

 

 props 및 state 값 변화시 render가 일어나며 re-render가 실행되면 안되는 부분이 re-render되면 성능상 문제가 될수 있으므로 해결해야 함

( class component에서는 shouldComponentUpdate를 사용하고 if문 생성 후 state 혹은 props 값이 변경되는 경우, update가 일어나야 할 경우는 return true를 해주어 render가 일어나게 하고 아닐 경우에는 false return하여 막아 줄 수 있음, Component 대신 PureComponent로 선언시 shouldComponentUpdate를 자동으로 관리함)

 

 

★ class의 lifecycle “constructor -> render -> ref -> componentDidMount -> (setState/props의 값 변경 -> shouldComponentUpdate(true) -> re-render -> componentDidUpdate) -> 부모 component에 의해서 자식 component가 사라질 경우 -> componentWillUnmount -> 소멸"

 

 

★ 비동기 요청을 하는 경우 componentDidMount()에서 작업을 하고 메모리 해제는 componentWillUnmoun()에서 작업을 함, ex) interval의 경우 component 제거 시 따로 제거를 해주지 않을시 계속 실행이 되고 있기 때문에 componentWillUnmount()에서 해제를 해야함

 

 

componentDidUpdate는 setState가 변경 될 때마다 실행이 되므로 조건문을 넣어 조건에 따라 실행이 될 것들을 잘 선언해야 함

 

HOOKS

Hooks에서는 state 변경 시 함수 전체가 render 되기 때문에 속도 측면에서 class보다 느릴 수 있음

 

 

Hooks setState의 경우도 callback 함수로 값을 받으면 비동기 문제 해결 가능( 이전 값을 참조시에도 사용)

 

 

setState 여러개를 동시 사용하면 render가 여러번 일어날것 같으나 비동기로 동작하므로 한 번의 render만 동작

 

 

★ Hooks의 경우  function component를 memo로 감싸 줄 경우 purecomponent와 같이 동작, re-render를 원하지 않는 component의 경우 purecomponent or memo를 적용할 수 있으며 모든 자식 component가 pure일 경우 부모 component에도 pure 적용

 

 

★ useState의 경우 setState를 사용 할 경우 render가 되고 useRef의 경우 render되지 않음, 값이 바뀌어도 render를 하고 싶지 않은 경우에는 useRef를 사용, 변화 된 값을 기록하는 것이라 생각

 

 

★ render안의 setState는 무한루프를 생성하기에 사용하면 안됨

 

 

★ Hooks에서 componentDidMount() 혹은 componentWillUnmount()를 사용하고 싶은 경우는 useEffect를 사용

 

 

 함수 component의 경우 매번 다시 실행되야 한다는 특성 때문에 useEffect가 매번 실행이 된다, 1:1 대응은 아니지만 LifeCycle처럼 사용하고 싶은 경우

 

useEffect(() => {                                    --> DidMount / DidUpdate

 interval.current = setInterval(change, 100);

return () => {                                        --> WillUnmount

 clearInterval(interval.current);

}

}, [update]);                                          --> DidUpdate

 

 

★ useEffect는 화면이 바뀐 후 발생하고 useLayoutEffect는 화면이 바뀌기 전에 발생

 

 

★ 불 필요한 함수가 연속적으로 실행되는 경우 useMemo를 선언하여 안쪽에 함수를 넣어줄 경우 이전 return 값을 기억하고 재실행을 하지 않음, 뒤 배열요소에 어떠한 값이 들어왔을때 실행하고 싶은경우 요소를 넣으면 됨

 

 

★ 함수 자체 생성 시간이 너무 오래 걸리며 재 생성 될 필요가 없는 함수의 경우 useCallback을 사용하면 함수 자체를 기억하여 재 생성하지 않음

 

 

useCallback의 경우 함수 자체를 다 기억하기에 변해야하는 변수의 경우도 변하지 않을수 있기 때문에 그러한 것들을 잘 고려하여 사용해야 하며 변경 되어야될 경우 배열요소에 넣어주면 됨

 

ARRAY

★ 반복문의 경우에는 성능 문제로 보통 따로 component로 빼서 만듬( 가독성, 재사용성 및 성능 최적화)

 

 

React의 JSX에서 반복문은 Array.map을 사용하여 return 값으로 tag를 넘김, tag에는 key 속성을 꼭 넣어줘야 한다( 성능 최적화를 위함, React가 배열 삭제시 위치를 기억하기 위함): 요소가 추가만 되고 삭제 기능이 없는 경우는 keyindex로 써도 큰 문제가 되지 않음

 

 

 React에서 배열 요소 추가시 .push를 사용하면 안됨, 불변성 유지 관점에 큰 문제가 됨 […array, 1]와 같이 추가

React render를 하는 기준이 이전 state랑 새로운 state가 다를때인데 .push 사용시 react가 변화를 감지하지 못하기때문에 문제가 됨, React에서는 배열 직접 수정이 아닌 새 배열을 만들어내는 함수 concat, slice, map, filter 사용!

 

 

 

 

★ node 내부 모듈에 대해서는 require 쓰고 react에서는 import를 주로 사용

 

 

화살표 함수가 자동적으로 binding을 해주기 때문에 constructor 함수안에 binding을 할 필요가 없어짐( state) 

  babel에서 화살표 함수 해석을 해줌

 

 

배포 시 보안상의 이유로 웹 내에서 보이지 않도록 React, Redux 데이터구조를 숨겨야 함

 

 

Props는 자식 component에서 절대 바꿔주면 안됨 부모에 의하여 관리가 되어야 함, 바꿔줘야 할 경우 state에 넣어주어 관리

 

 

Tag를 if문으로 설정해서 보여주어야 할 경우 component로 따로 빼고 props로 조건을 받는 방식으로 하면 깔끔

 

 

JSX내에서 if문 혹은 for문을 쓰는 방법은 즉시 실행 함수를 선언하고 그 안에 사용하면 됨. 하지만 코드가 더러워지기 때문에 추천하지는 않음,

   {(() => {

    if

   })()}

 

 

비동기 함수를 다루는 경우 클로저의 문제가 발생 할 가능성이 있음, 변수를 setInterval 바깥에 선언할 경우 변수가 setInterval 하는 시점으로 계속 고정되기 때문에 setInterval 함수 안으로 가져와야 변수가 항상 최신화가 됨

 

 

함수안에서 함수를 불러야 할 경우는 high order function을 사용가능, ex) () => () => {}, onClick에는 함수를 넣어야 event 발생이 됨. , this.onClickBtn(element)onClick에 넣어야 하는 경우 이것은 함수가 아닌 결과물이므로 () => this.onClickBtn(element)으로 넣어야 하며 이것을 high order function으로 표현 가능

 

 

setInterval, setTimeout과 같은 함수는 꼭 DidMount에서 사용 할 필요는 없음. 함수내에서 사용 가능하나 componentWillUnmount에서 clear는 필수

 

 

불 필요한 render를 막기 위하여 PureComponent, memo를 넣어줘야 함

 

 

state를 사용하지 않는 부분은 재사용성을 위하여 꼭 분리를 하는 것을 추천

  

 

★ Hooks useEffect에서 componentDidUpdate 조건을 잘 설정해주어야 함, componentDidMount도 동시 실행이 되는 이유 때문

 

 

★ Hooks 사용시 함수에 console.log()를 넣어 실제로 내가 필요할때만 호출이 되는지 확인하는 디버깅 필요

 

 

부모에서 자식에게 props로 함수를 넘겨 줄 경우 자식에서 memo를 선언하더라도 함수가 재실행되는 경우 props가 변경 된 것으로 인식하여 매번 새로운 render를 실행함, 이것을 막기 위하여 useCallback으로 함수를 감싸주면 해당 현상을 막을수 있음

 

 

★ componentDidUpdate에서는 update 조건을 한 블럭안에 여러개 선언이 가능하나 Hooks의 경우 useEffect에서는 update되야될 조건 별로 배열 요소에 정리하여 따로 선언해야 함

 

 

useEffect에서 componentDidMount를 하지 않고 componentDidUpdate만 하고 싶은 경우, 꼼수

const mounted = useRef(false);

useEffect(() =>{

 if (!mounted.current) {

  mounted.current = true;

} else {

 하고 싶은 동작;

}

}, [바뀌는 값]);

 

useReducer

useReducer와 context로 소규모 프로젝트에서는 redux의 흉내를 낼수는 있으나 대규모 프로젝트에서는 아직도 redux가 필요

 

 

★ 부모 자식간의 component 관계가 복잡하여 props로 데이터 전달이 너무 길 경우 re-render의 위험부담이 있으며 context API 및 Redux를 사용하여 해결 가능

 

 

state가 너무 많아지는 경우 관리를 위해서 useReducer를 사용하면 하나로 통일하여 관리가 가능

 

 

★ component props 넣어주는 함수는 모두 useCallback을 사용

 

 

useReducer 사용법은 dispatch안에 들어가는 action 객체를 선언하고 action에는 type 변화되는 state를 적어줘야함, reducer는 action을 해석해서 직접적으로 state를 변화시켜주는 매개체, 불변성을 지키며 state 값 변경, actiondispatch 할 때마다 reducer 함수가 실행 됨

 

 

state를 initialState로 정해놓으면 그 영역은 절대 수정 할 수 없음, state를 수정하기 위해서는 어떠한 event 발생 시 action을 실행해야하며 action 실행시 dispatch해야하며 action을 어떻게 처리할지는 reducer에서 관리, 기록을 함, ex) 이전 state값에서 수정하고 싶은 값을 변경

{…state, winner: action.winner};

 

 

★ reducer 사용시 불변성을 지키기 위해 얕은복사를 하다보면 가독성에 문제가 될수 있으며 그 문제를 해결할수 있는 것이 immer라이브러리

 

 

★ Redux에서는 dispatch가 동기적으로 동작되나 useReducer에서는 dispatch가 비동기적으로 동작

 

 

불필요한 render가 발생할 시 useRef와 useEffect로 확인 가능, useRef를 함수내에 선언 후 ref.current로 현재 props 값과 useEffect에서 전달받은 props 값들을 console.log로 비교하여 변하는 값, 변하지 않는 값을 확인

 

 

useMemo로 함수의 return 값만 최적화를 할 수 있는 것은 아니며 component의 경우도 최적화 가능, component의 경우도 return 값이기 때문, 배열 요소에 update되어야만 하는 값만 넣어서 최적화를 할 수 있음

 

 

★ 함수 component를 감싸는 memo는 props의 변화를 감지함, 변하지 않을 경우 render하지 않음( 최적화)

 

 

memo 적용시 props에 객체를 넣을 때 조심해야 함. 객체끼리는 참조 관계 때문에 “===” 의 결과를 잘 생각해야 함

  

 

useMemo로 context API에 사용하기 위한 data를 묶어야 .Provider로 JSX tag를 감쌀경우 성능저하가 일어나지 않음, 꼭 변해야 하는 값은 useMemo의 배열 요소에 추가( Cashing 작업이라 불림)

 

 

dispatch는 절대 안바뀌는 함수이기 때문에 굳이 바뀌는 목록인 배열 요소에 추가를 하지 않아도 됨

 

 

dispatch를 통하여 꼭 state를 변경하여 보내는 것 뿐만 아니라 state가 함수일 경우 함수의 arguments로 들어갈 값들을 dispatch를 통하여 보내고 함수내부에서 계산 후 return 값으로 state의 값을 변경 할 수 있음

 

 

onContextMenu는 오른쪽 클릭 event 메뉴

 

 

★ re-rendering이 쓸데 없이 될만한 곳은 memo를 기본적으로 넣어본다. component에 memo를 넣었을 경우 하위 component에도 memo를 적용해주어야 함.

 

 

함수가 자주 불리더라도 직접 View에 그려지는 부분은 cashing을 해주는 것이 중요, useMemo를 사용

 

 

context API를 사용 할 경우 값을 불러 올 때 함수가 호출되지만 실제로 render가 계속해서 되는지는 확인해보고 한 번만 render 된다면 큰 문제는 없음

 

 

return 부분을 따로 빼고 싶은 경우 한 파일에 2개의 component를 선언하고 return 부분을 다른쪽으로 빼서 선언하는 것도 가능

 

 

 조건 관련

 '', false, 0, undefined, null, NaN은 다 없는 값(falsy)으로 칩니다. 그 외에는 있는 값(truthy)입니다.

A falsy 값중에 해당된다면 A || 'ABC' 'ABC'가 되고, truthy이라면 A || 'ABC' A가 됩니다.

&&는 반대로 앞에 것이 truthy 값이어야 다음 값이 실행됩니다.

A && 'ABC'에서 A falsy 값이라면 A가 되고 A && 'ABC'에서 A truthy 값이라면 'ABC'가 됩니다. ||랑 반대입니다.

'Web > React' 카테고리의 다른 글

[React] 커스텀 훅 및 useCallback  (0) 2021.05.18
[React] 라우터 및 코드 스플릿  (0) 2021.05.18
[React] React에서 index.html( css)  (0) 2021.05.17
[React] 메뉴얼 React webpack 환경 설정  (0) 2021.05.17
[React] React props  (0) 2021.05.17