useEffect cleanup 함수 관련 지식이 모자람을 느끼고 들은 섹션
✍ Effects, Reducers & Context
📌 Effect, Side Effect
리액트 라이브러리는 UI를 렌더링하는 임무가 있다.
사용자가 무엇인가와 상호작용하게 하는 것.
Side Effects는 앱에서 일어나는 다른 모든 것을 뜻함
- http request
- rocal storage 저장
이것들은 모두 애플리케이션에서 고려해야 한다.
그러나 이러한 작업들은 화면에 무언가를 가져오는것과는 직접적인 관련은 없다.
따라서 이것들은 일반적인 컴포넌트 함수 밖에서 일어나야 한다.
예를 들어 http request를 컴포넌트 안에서 시행하면 state가 변경될 때마다 계속 받아오게 된다.
무한 루프로 빠질 수도 있음.
따라서 side effect는 컴포넌트 안으로 들어가면 안된다
useEffect() Hook
이럴 때 useEffect 훅을 사용할 수 있다.
내장 훅
useEffect(() => {}, [])
두 개의 매개변수, 두 개의 인수와 같이 호출됨
첫 번째 인수는 함수
모든 컴포넌트 평가 후에 지정된 의존성이 변경된 경우에 실행되어야 하는 함수
지정된 의존성은 두 번째 인수로 넣어줘야 한다[]
첫 번째 함수에 어떤 side effect code도 넣을 수 있음.
그러면 그 코드는 의존성이 변경된 경우에만 실행될 것
useEffect는 사이드이펙트를 처리하기 위해 존재
사이드이펙트는 http 요구같은 것, 아니면 키 입력을 받고 응답하고 다른 액션을 실행하는 것,,,
이런 식의 사이드이펙트가 존재한다(사용자 입력 데이터의 사이드이펙트)
무언가에 대한 응답으로 실행되는 코드를 다루는데 도움이 된다.
어떤 액션에 대한 응답으로 실행되는 액션이 있다면 useEffect가 크게 도움된다
종속성으로 추가할 항목 및 추가하지 않을 항목
- 상태 업데이트 기능을 추가할 필요는 없다
- react는 해당 함수가 절대 변경되지 않도록 보장하기 때문
- 내장 API 또는 함수를 추가할 필요가 없다
- fetch()나 localStorage같은 것들 (브라우저에 내장된 함수 및 기능, 따라서 전역적으로 사용 가능) : 이러한 브라우저 API/전역 기능은 React 구성 요소 렌더링 주기와 관련이 없으며 변경되지 않음
- 변수나 함수를 추가할 필요가 없다
- 구성 요소 외부에서 정의했을 것 (별도의 파일에 새 도우미 함수를 만드는 경우) : 이러한 함수 또는 변수도 구성 요소 함수 내부에서 생성되지 않으므로 변경해도 구성 요소에 영향을 주지 않는다.(해당 변수가 변경되는 경우, 또는 그 반대의 경우에도 구성 요소는 재평가되지 않는다)
결과적으로
effect 함수에서 사용하는 모든 것들을 추가해야 한다.
구성 요소(또는 일부 상위 구성 요소) 가 다시 렌더링 되어 이러한것들이 변경될 수 있는 경우,
그렇기 때문에 컴포넌트 함수에 정의된 변수나 상태, 컴포넌트 함수에 정의된 props 또는 함수는 종속성으로 추가되어야 한다.
useEffect에서 cleanup 함수 사용하기
return () => {};
클린업 함수
이 useEffect가 실행될 때마다 이 클린업 함수가 실행된다
우리가 이벤트를 특정한 컴포넌트가 DOM에서 unmount될 때마다 실행된다 == 컴포넌트가 재사용될 때마다 실행
따라서
cleanup 함수는 모든 새로운 사이드이펙트 함수가 실행되기 전에 & 컴포넌트가 제거되기 전에 실행된다
그리고 첫 번재 사이드이펙트 함수가 실행되기 전에는 실행되지 않는다.
📌 useRedcer 및 Reducers
react 내장 훅, state 관리를 도와준다.
복잡한 state에 좋음.
여러 state가 같이 바뀌거나 관련될 때
이런 겨우 useReducer을 useState대신 쓸 수 있다.
하지만 강력하다고 해서 좋은 것은 아님.
대부분의 경우에는 useStat를 사용하는 것이 좋다.
useReducer
예를 들어 enteredEmail과 emailIsValid 라는 useState가 있을 때
이 둘은 서로 중첩되기 때문에 useReducer을 사용할 수 있다.
필요할 때
- 함께 속하는 state들이 있는 경우
- 다른 state에 의존하여 state를 업데이트 하는 경우
코드const [state, dispatchFn] = useReducer(reducerFn, initialState, initFn);
state
- state 스냅샷을 얻음
dispatchFn - state를 업데이트해줄 수 있음. 새로운 state를 업데이트 하는 대신에 액션을 dispatch한다.
이 액션은
useReducer의 첫 번째 인수가 소비한다
reducerFn - 함수, 최신 state stnapshot을 자동으로 가져온다.
- 그리고 디스패치된 액션을 가져온다.
- react가 관리하는 최신의 state를 반환.
initialState - 초기 state값 설정
initFn - 초기 state가 더 복잡하 경우 초기 값 설정 ( http request 결과라든지..)
reducer의 reducerFn함수는 component 밖에서 만든다
이유 : 컴포넌트 함수 내부에서 만들어진 어떤 데이터도 필요하지 않기 때문
useState vs useReducer
useState
- 주요 state 관리 도구
- 개별 state를 다루기 적합
- state 업데이트가 쉽다.
- 종류가 다양하지 않다면 사용하는 것이 좋다
useReducer
- 복잡한 state가 있을 때
- 복잡할 수도 있는 로직을 별도의 리듀서 함수로 이동시킬 수 있다.
- 연관된 state 조각들로 구성된 state를 다룰 때.
📌 contextAPI
props를 통해 많은 컴포넌트를 거쳐 데이터를 전달할 때 문제가 발생한다.
보통 이런 경우에는 함수 handler을 통해 데이터를 전달하지만 이것도 비슷한 문제가 발생한다.
함수를 쓰지도 않는 컴포넌트를 통해서 원하는 컴포넌트에 전달함.
=> prop 채인이 만들어짐
contextAPI를 이용하면 이 문제를 해결할 수 있다.
앱에 바로 전달할 수 있다
작동 방식
auth-context.js
같은 파일을 만든다.
React.createContext()로 컨텍스트 객체를 생성한다.
대부분의 경우에는 객체가 들어간다. 그냥 문자열도 가능
const AuthContext = React.createContext({
isLoggedIn:false
})
export default AuthContext;
이 특적 컨텍스트를 만들고 내보내는 작업
받는 입장
- 일단 context가 사용될 모든 곳을 감싸야 한다. 모든 곳에서 필요하다면
App.js
를 활용하거나 해야 한다이제 감싼 컴포넌트 안에서는 모두 context에 접근할 수 있다. <AuthContext.Provider> 감싸기 </AuthContext.Provider>
리스닝하기
값에 접근하려면 리스닝해야 한다
AuthContext 소비자 아니면 react hook을 이용해서 리스닝한다.
<AuthContext.Consumer>
{(ctx) => {
return jsx(감싸기) // 여기서 ctx.isLoggedin 같은 접근이 가능해진다
}}
</AuthContext.Consumer>
소비자는 자식을 가지고(함수를 가지고)
인수로 context 데이타를 가져온다 isLoggedin: false
✨ 중요
사실 기본값 isLoggedin : false
가 있으면 공급자는 필요하지 않다.
그러나 실제로는 변할 수 있는 값을 주기 위해서는 공급자가 있어야 한다.
공급자에서 값을 변하게 하는 법
<AuthContext.Provider
value={{
우리 객체 전달 ex isLoggidin:false
}}>
감싸기
</AuthContext.Provider>
이 공급자에서 state 내용을 집어넣으면 하드 코딩 대신 변화하는 값을 설정할 수 있음.
useState가 그렇듯이 react에 의해 업데이트된다.
결과적으로 isLoggin을 전달하기 위해 props drilling을 사용할 필요가 없어짐.
context hook
컨텍스트를 사용하고 리스닝할 수 있게 해준다
사용법const ctx = useContext(AutContext);
이렇게 해주면 소비자 필요없이 사용할 수 있다.
context를 동적으로 만들기
<AuthContext.Provider
value={{
isLoggidin:false,
onLogout: logoutHandler // 📌 ()=>{} ide 자동완성을 위해 추가하는 것이 좋다
}}>
감싸기
</AuthContext.Provider>
이런식으로 전달하고
모든 리슨닝 컴포넌트는 logoutHandler 함수를 활용할 수 있다
함수를 전달할 수 있다.
함수 전체에 거쳐서 state를 관리하고 state를 변경할 수 있다.
따라서 props를 제거할 수 있다.
Prop? Context?
대부분의 경우 prop을 사용해서 컴포넌트에 데이터를 전달.
프롭은 component를 구성하고 전달하는 메커니즘이기 때문.
따라서 많은 컴포넌트를 통해 전달하고자 하는 것이 있는 경우에만,
또 매우 특정적인 일을 하는 컴포넌트로 전달할 때만 컨텍스트를 사용하는 것이 좋다.
많이 사용하면 뭘 사용해야 할지 확실히 알수 있다고 함😗
Context Limitations (컨텍스트 제한)
앱 전체 또는 컴포넌트 전체에는 좋다
하지만 컴포넌트 구성을 대체할 수는 없다.
=>
- 구성을 하려면 props
- 전체 앱 / 컴포넌트에서 state 관리를 하려면 컨텍스트
단점
변경이 잦은 경우에는 context는 최적화되어있지 않다
'✍ 공부 > React' 카테고리의 다른 글
React는 어떻게 동작할까?_리액트가 동작하는 방식 (0) | 2022.07.18 |
---|---|
함수형 컴포넌트로 ref 보내기 | forwardRef에 대해 알아보자 (0) | 2022.06.12 |
React 프로젝트 구조 잡기 (0) | 2022.06.08 |
[ 🐱💻 강의 노트 ] React 완벽 가이드 강의 정리 섹션 27 | React + TypeScript 사용하기 (0) | 2022.06.01 |
[ 🐱💻 강의 노트 ] React 완벽 가이드 강의 정리 섹션 29 | 리엑트 요약 및 핵심 기능 (0) | 2022.05.31 |