-
[ReactJS] React state 관리웹 개발/ReactJS 2021. 5. 14. 21:40반응형
일반 변수는 변수값이 변해도 새롭게 렌더링 되지 않는다.let count = 1;
이를 해결하기 위해 state를 관리하여 DOM을 업데이트 하는 react hook들을 정리해보려 한다.
useState
데이터 공간 생성
const [데이터, 데이터변경함수] = useState(초기데이터);
ex)const [count, setCount] = useState(0); .. <span onclick = {()=>{setCount(count+1)}>
-> onclick 이벤트를 통해 useState의 변수값이 바뀌면 컴포넌트가 새롭게 렌더링 된다.
이 때 랜더링마다 count 값을 업데이트 되는 것이 아니라 랜더링을 통해 새롭게 생성된 독립적인 상수를 보는 원리이다.
** Immutability
react는 useState의 변수를 직접 바꾸지 않고 deep copy를 통해 state를 변경하는 것을 권장한다.
state를 직접 변경하게 되면 특정 객체가 변경되었을 때 이 객체를 참조하고 있던 객체에서도 변경이 일어난다.
하지만 deep copy를 통해 변경이 일어난 객체의 프로퍼티만 비교함으로써 React에서 최적화가 가능하다.
const [count, setCount] = useState(0); function changeCount(){ var newCount = [..count]; newCount = count +1; setCount(newCount); } <span onclick = {()=>{changeCount()}>
Immutability
객체가 생성된 이후 그 상태를 변경할 수 없는 디자인 패턴
useRef
특정 DOM 선택
ex)
- useRef() 를 사용해 Ref 객체 생성const nameInput = useRef();
- 선택하고 싶은 DOM 에 ref 값으로 설정
<input name="name" placeholder="이름" onChange={onChange} value={name} ref={nameInput} />
- Ref 객체의 .current 값은 우리가 원하는 DOM 을 가르키게 된다.nameInput.current.focus();
- 전체 코드import React, { useState, useRef } from 'react'; const nameInput = useRef(); const onReset = () => { setInputs({ name: '', nickname: '' }); nameInput.current.focus(); }; ... <input name="name" placeholder="이름" onChange={onChange} value={name} ref={nameInput} />
useEffect
각각의 이펙트 버전은 매번 랜더링에 랜더링에 속한 props와 state를 본다.
이전 이펙트는 새 prop과 함께 리랜더링 되고 난 뒤에 클린업된다.
이펙트의 클린업은 “최신” prop을 읽는 것이 아니라 클린업이 정의된 시점의 랜더링에 있던 값을 읽는 것입니다.리액트가 {id: 20} 을 가지고 UI를 랜더링한다. 브라우저가 실제 그리기를 한다.
화면 상에서 {id: 20} 이 반영된 UI를 볼 수 있다.
리액트는 {id: 10} 에 대한 이펙트를 클린업한다.
리액트가 {id: 20} 에 대한 이펙트를 실행한다.-> 리액트는 DOM과 함께 리액트 트리 바깥에 있는 것들을 props와 state에 따라 동기화 할 수 있게 한다.
특정한 이펙트가 불필요하게 다시 실행되는 것을 방지하고 싶다면 의존성 배열을(“deps” 라고 알려진 녀석이죠) useEffect 의 인자로 전달할 수 있는 것입니다.
첫 번째 요소 : 함수
두 번째 요소 : 의존값이 들어있는 배열 (deps)
- 컴포넌트가 마운트 됐을 때 (처음 나타났을 때),
- 언마운트 됐을 때 (사라질 때),
- 업데이트 될 때 (특정 props가 바뀔 때)
- deps가 비어있을 때 : 컴포넌트가 마운트 됐을 때만 불러옴useEffect(() => { console.log('컴포넌트가 화면에 나타남'); return () => { console.log('컴포넌트가 화면에서 사라짐'); }; }, []);
- deps 값이 있을 때 : deps 값이 언마운트시, 값이 바뀌기 직전에도 호출이 됩니다.
useEffect(() => { console.log('user 값이 설정됨'); console.log(user); return () => { console.log('user 가 바뀌기 전..'); console.log(user); }; }, [user]);
useMemo
특정 함수로 연산값 재 사용 -> 랜더링 시 함수가 또 호출되는 것을 방지
const count = useMemo(() => countActiveUsers(users), [users]);
useCallback
useCallback 은 특정 함수를 새로 만들지 않고 재사용
const onCreate = useCallback(() => { const user = { id: nextId.current, username, email }; setUsers(users.concat(user)); setInputs({ username: '', email: '' }); nextId.current += 1; }, [users, username, email]);
React.memo
리랜더링이 필요한 상황에만 리랜더링할 수 있도록 함
const CreateUser = ({ username, email, onChange, onCreate }) => { return ( <div> <input name="username" placeholder="계정명" onChange={onChange} value={username} /> <input name="email" placeholder="이메일" onChange={onChange} value={email} /> <button onClick={onCreate}>등록</button> </div> ); }; export default React.memo(CreateUser);
useReducer
useState와 유사한 기능으로 상태관리를 한다.
- useReducer는 컴포넌트의 상태 업데이트 로직을 컴포넌트에서 분리해서 관리할 수 있음
- reducer 는 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환해주는 함수function reducer(state, action) { // 새로운 상태를 만드는 로직 // const nextState = ... return nextState; }
- 컴포넌트가 관리하는 상태값이 여러개일때 용이
const [state, dispatch] = useReducer(reducer, initialState);
- state : 우리가 앞으로 컴포넌트에서 사용 할 수 있는 상태
- dispatch : 액션을 발생시키는 함수
- 첫번 째 파라미터 : reducer 함수
- 두번째 파라미터 : 초기 상태
예시import React, { useReducer } from 'react';
reducer 함수
function reducer(state, action) { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } }
function Counter() { const [number, dispatch] = useReducer(reducer, 0); const onIncrease = () => { dispatch({ type: 'INCREMENT' }); }; const onDecrease = () => { dispatch({ type: 'DECREMENT' }); };
https://estaid.dev/reasons-to-maintain-immutability-with-react/
https://rinae.dev/posts/a-complete-guide-to-useeffect-ko반응형'웹 개발 > ReactJS' 카테고리의 다른 글
[ReactJS] Module이란 무엇일까? (0) 2022.02.10 [ReactJS] 네이버, 카카오 지도 api 사용해 개발해보자 (1) - 지도 가져오기 (0) 2021.07.22 [ReactJS] 리액트의 특징 및 원리 (0) 2021.04.27 [ReactJS] 서버사이드 렌더링(SSR)과 클라이언트사이드 렌더링(CSR)이란 (0) 2021.04.27 [ReactJS] React 기본 코드 구조 및 component 생성 (0) 2021.04.15