-
react ( Udemy강의 ) - 3. Effects, Reducers & ContextReactJS 2022. 4. 20. 11:11
Advanced, yet super-important Features!
1. Effect ( Side Effect )
- 애플리케이션에서 일어나는 다른 모든 것들
EX) http 리퀘스트에 대한 응답 / 브라우저 저장소에 무언가를 저장 / 타이머나 간격을 설정
- 사이드이펙트( : 응답으로 실행되는 액션 )를 처리하기 위해 존재
useEffect( () => { }, [dependencies] );
첫번째 인자 : 함수 - 모든 컴포넌트 평가 후에 실행되어야하는 함수
두번째 인자 : 의존성 지정 - 의존성으로 구성된 배열
구성요소( 또는 일부 상위 구성 요소 )가 다시 렌더링 되어 이러한 "것들"(의존성요소)이 변경될 수 있는 경우
ex_01) 유효성 검사시 활용
useEffect(() => { setFormIsValid( enteredEmail.includes('@') && enteredPassword.trim().length > 6 ); }, [enteredEmail, enteredPassword]);
디바운싱 : 사용자 입력을 디바운스(그룹화)
클린업함수 : 클린업 프로세스로써 실행,
모든 새로운 사이드이펙트 함수가 실행되기 전에 그리고 컴포넌트가 제거되기 전에 실행
첫 번째 사이드이펙트 함수가 실행되기 전에는 실행되지 않습니다.
이펙트 함수가 실행되기 전에 트리거됨.
useEffect(() => { const identifier = seTimeout( () => { setFormIsValid( enteredEmail.includes('@') && enteredPassword.trim().length > 6 ); }, 500); return () => { clearTimeout(identifier); // 새로운 타이머를 설정하기전에 마지막 타이머를 지운다. }; // 클린업함수 }, [enteredEmail, enteredPassword]);
2. Reducers
useReducer( )
state관리를 도와줌, 더 복잡한 state에 유용
* 다른 state를 보고 새로운 state를 도출하는 건 해서는 안되는 일이다! *
( 대부분 작동은 잘되지만 어떤 경우에는 작동하지 않을 수 있다. )
-> 다른 state기반으로 하는 state를 업데이트하면 state를 하나로 만들거나(복잡) Reducer 사용
const [state, dispatchFn] = useReducer(reducerFn, initialState, initFn);
state : 최신 스냅샷
dispatchFn : state스냅샷을 업데이트할 수 있게 해주는 함수, 새로운 state 값을 설정하는 대신 액션을 디스패치
reducerFn : 리듀서함수, 최신 state 스냅샷을 자동으로 가져오는 함수, 디스패치된 액션을 가져옴
새로운 업데이트된 state를 반환
initialState : 초기 state 설정
initFn : 초기 state를 설정하기 위해 실행해야하는 함수
액션은 항상 같은 구조를 가져야한다.
EX01)
const emailReducer = (state, action) => { if(action.type === "USER_INPUT") { return { value: action.val, isValid : action.val.includes("@") }; } if(action.type === "INPUT_BLUR) { return { value: state.value, isValid : state.value.includes("@") }; } return { value: "", isValid: false }; }; const Login = (props) => { const [emailState, dispatchEmail] = useReducer(emailReducer, { value:"", isValid:null, }); const emailChangeHandler = (event) => { dispatchEmail({ type:"USER_INPUT", val: event.target.value }); }; };
* 참조 깃 주소 : https://github.com/PHyeonMIN/react-study/blob/main/EX_06/src/components/Login/Login.js
useReducer & useEffect
객체 dstructuring : 객체의 특정 속성을 추출하는 것
const { isValid : emailIsValid } = emailState; const { isValid : passwordIsValid } = passwordState; // 값할당 : 별칭할당 useEffect( () => { const identifier = setTimeout(() => { setFormIsValid(emailIsValid && passwordIsvalid); }, 500); return () => { clearTimeout(identifier); }; }, [emailIsValid, passwordIsValid] )
: 해당 유효성을 만족하면 실행되지않게하는 코드 , 이펙트가 불필요하게 실행되는 것을 피하기 위함
전체 개체 대신 특정 속성을 종속성으로 전달!
+ 이펙트 의존성으로 프롭이 있는 경우, 프롭이 변경될 때마다 이펙트를 다시 실행x , 특정 프롭만 변경
-> 객체 디스트럭처링을 사용
useState() vs useReducer()
State
- 스냅샷들이 서로 독립
- 주요 state 관리 도구
- 개별 state 및 데이터들을 다루기에 적합, 간단한 state에 적합, state 업데이트가 쉬움
Reducer
- 복잡한 state, state보다 더 강력( 리듀서 함수를 쓸 수 있기에 )
- 연관된 state 조각들로 구성된 state 관련 데이터를 다루는 경우 ex ) 폼 인풋 state 경우
- 복잡한 state 업데이트가 있는 경우
3. Context(Context API)
리액트 컨텍스트 : 리액트에 내장된 내부적인 state 저장소 / 긴 props 체인 교체시 사용
+ 집중적이고 분리된 접근 방식
사용법
1. 컨텍스트 객체 생성
import React from 'react'; const AuthContext = React.createContext({ isLoggedIn : false }); export default AuthContext;
2. 공급 - 접근권한
<AuthContext.Proveider value={{ isLoggedIn: false, onLogout:logoutHandler }}> </AuthContext.Proveider>
: 감싼 모든 컴포넌트와 모든 자손 컴포넌트들은 이제 해당 컨텍스트에 접근 가능
+ 기본값이 존재하면 공급자는 필요없다!
* 리액트 프래그먼트로 사용가능!
3. 소비 - 연동, 리스닝
방법1 - 소비자
return ( <AuthContext.Consumer> {(ctx)=>{ return( JSX코드 ); }} </AuthContext.Consumer> );
ctx : 컨텍스트 데이터
방법2 - 훅
const ctx = useContext(AuthContext);
컨텍스트 제한
- 다른 용도 사용x , 구성을 하려면 props 사용
- 변경이 잦은 경우 - 1초에 한번씩 state가 변경되는 경우 -> 리덕스!
Rules of Hooks
1. 리액트 훅은 리액트 함수(JSX반환하는 함수)에서만 호출 or 사용자 정의 훅
2. 리액트 컴포넌트 함수 또는 사용자 정의 훅 함수의 최상위 수준에서만 호출해야함
중첩 함수에서 훅 호출 x
block 문에서 호출 x
3. useEffect - 항상, 참조하는 모든 항목을 의존성으로 useEffect 내부에 추가해야 한다.
인풋 포커스 : useImperativeHandle & forwardRef
useImperativeHandle : 컴포넌트나 컴포넌트 내부에서 오는 기능들을 명령적으로 사용할 수 있게 해줌
일반적인 state 프롭관리를 통하지 않고 부모 컴포넌트의 state를 통해 컴포넌트를 제어하지 않고 프로그래밍적으로 컴포넌트에서 무언가를 직접 호출하거나 조작해서 사용
const Input = React.forwardRef((props, ref) => { useImperativeHandle(ref , () => { return { focus : activate }; });
첫번째 인자 : 참조 대상
두번째 인자 : 객체를 반환해야하는 함수 , 외부에서 사용할 수 있는 모든 데이터를 포함
내부 함수 또는 내부 변수 또는 무엇이든 그 이름을 통해 외부에서 접근할 수 있는 것을 가리킴
+ 두번째 인자 활성화를 위해 React.forwardRef으로 내보낸다.
React.forwardRef
첫번째 인수 : 컴포넌트 함수
-> ref프롭 사용가능 + ref을 노출 + ref와 함께 제어하거나 사용
-> 부모 컴포넌트에 연결한 다음, 부모 컴포넌트 안에서 참조를 통해 그 컴포넌트를 사용하고 기능을 트리거 가능
깃허브 주소 : https://github.com/PHyeonMIN/react_Study/blob/main/EX_06/src/components/UI/Input/Input.js
'ReactJS' 카테고리의 다른 글
react ( Udemy강의 ) - 4. React 최적화 (0) 2022.04.28 react - 아코디언 메뉴 (0) 2022.04.25 react ( Udemy강의 ) - 2. Fragments, Portals & Refs ( Toolbox ) (0) 2022.04.20 react ( Udemy강의 ) - 1. Component, CSS (0) 2022.04.12 react기초 - 노마더코더 ( 트위터 클론코딩 ) (0) 2022.03.13