ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • react ( Udemy강의 ) - 3. Effects, Reducers & Context
    ReactJS 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

    댓글

Designed by Tistory.