• React

[React] useEffect / useReducer

man_on 2021. 10. 24. 23:46
반응형

 

 

 

     


     

    useEffect / useReducer

     

     

    [ 기초 지식 ]

     

     

     

    component는 lifecycle이 존재

    컴포넌트도 인생이 있다. 

     

           1. mount (생성, 처음 나타났을 때)

               : props로 받는 값을 컴포넌트의 로컬 상태로 설정할 때 / 외부 API요청 (REST API 등, 라이브러리 사용

                  setInterval을 통한 반복작업 혹은 setTImeout 통한 작업 예약

           2. unmount (사라질 때)

                : setInterval로 등록한 작업을 clear하기 (clearInterval, clearTimeout), 라이브러리 인스턴스 제거

           3. re-rendering (업데이트, 관련된 state가 변경되면 재렌더링)

     

     

     

    > component의 인생의 중간중간 hook을 걸 수 있다. (인생에 참견한다)

        이를 lifecycle hook이라고 하고, ' detail component등장전에 이것좀 해줘!' ' 업데이트 되고나서 이것좀 해줘!' 이런느낌

     

     

     

    class형

    componentDidMount (컴포넌트 첫 등장 후 실행할 코드)

    componentWillUnmount(컴포넌트 사라지기 전 실행할 코드)

    class Detail extends React.Component {
      componentDidMount(){
        //Detail 컴포넌트가 Mount 되고나서 실행할 코드
      }
      componentWillUnmount(){
        //Detail 컴포넌트가 Unmount 되기전에 실행할 코드
      }
    }

     

     

     

     

     

     

     

     

     

     

     

    useEffect 

     

     

    useEffect가 하는일 ?

      useEffect hook을 이용하여 react가 컴포넌트 렌더링 이후에 어떤 일을 수행하는지를 지정할 수 있다.

     

     

    useEffect의 주요역할은 side effect를 처리하는 것이다.

     

     

    //첫번째 파라미터에는 함수
    //두번째 파라미터에는 의존값 들어있는 배열 (deps)을 넣는다.
    
     useEffect(() => {
        effect
        return () => {
          cleanup
        }
      }, [input])

     

     

     1.  useEffect를 import 해온다.

     2. useEffect를 사용하고 콜백함수를 집어넣는다.

     3. 콜백함수에는 

           컴포넌트가 첫 등장해서 로딩 끝난후에 (mount끝났을 때)

            컴포넌트가 재렌더링 되고 난 후에 (update 되고난 후)

         실행할 코드를 작성한다.

    4. useEffect(() => {

       return () => {} 리턴 뒤넣은 함수(cleanup함수)는 컴포넌트가 사라질 때 실행된다.

    5. 두번째 파라미터에 의존값 있는배열 (deps)를 넣는다.

        비워놓으면 컴포넌트 처음 나타날때만 useEffect 호출된다.

     

     

     

    ✔️ 마운트 시 하는 작업

       - props로 받은 값을 컴포넌트의 로컬 상태로 설정

       - 외부 API 요청 (REST API)

       - 라이브러리 사용

       - setInterval 통한 반복작업 혹은 setTimeout

     

     

     

    ✔️ 언마운트 시 하는 작업

       - setInterval, setTImeout 사용하여 등록한 작업들 clear ( clearInterval, clearTimeout)

       - 라이브러리 인스턴스 제거

     

     

     

    ✔️ deps에 특정 값 넣기

     

        1. 파라미터에  아무것도 안 넣었을 경우

             리렌더링 될 때마다 함수 호출 (=모든 component render cycle마다 작동)

     

        1. deps에 빈 배열 - [ ]

             mount : 처음 mount 될 때 함수 호출 (리렌더링 시 X )

             unmount : cleanup 함수 호출

     

       2. deps에 의존 값 존재  - [dpes]

             mount : 처음 mount 될 때 함수 호출 + 의존값 업데이트 됬을 때

             unmount : unmount 될 때 cleanup함수 호출 + 값이 바뀌기 직전에도 호출

     

     

     

     

     : useEffect 안에서 사용하는 상태나, props가 있다면 deps에 넣어줘야한다.

       그렇지않으면 useEffect에 등록한 함수가 실행 될 때 최신 props나 상태를 가르키지않는다.

       ( effect 안에 있으면서 다시 렌더링되어서 변경되는 모든것들을 deps에 넣어줘야한다.)

     

     

     

      useEffect(() => {
        console.log("user값이 설정됨");
        console.log(user);
        return () => {
          console.log("user값이 바뀌기전...");
          console.log(user);
        };
      }, [user]);

    처음 mount
    user 리렌더링

     

     


     

     

    🔻 cleanup함수

          setTimeout 타이머 썼으면 타이머해제 해줘야 한다.

           예제에 'detail방문 시 2초후에 UI 사라지게 해라' 라고 했는데 2초전에 detail벗어나면 이상한일 일어날수도..

           clearTimeout(타이머이름) 

    //return+함수 (컴포넌트 사라질 때 특정코드 실행)
    useEffect(()=>{
      let 타이머 = setTimeout(()=>{ alert변경(false) }, 2000);
    
      return ()=>{ clearTimeout(타이머) }
    }, []);

     

     


     

     

     

    🔻 Debounding / Throttiling

     : 디바운싱과 쓰로틀링은 프로그램 기법 중 하나이다. 둘다 디바이스의 무리를 주지않기위해 사용된다.

     

    debounce는 연이어 발생한 이벤트를 하나의 그룹으로 묶어서 처리한다.

    throttle는 입력주기를 방해하지않고, 일정시간 동안의 입력을 모아서 한번씩 출력한다.

     

    ( user가 한글자씩 입력할 때 마다 데이터를 가지고오게되면, 성능면에서 비효율적이므로

     사용자가 입력이 다끝났을 때 입력데이터를 가져오는것을 debouncing이라 한다.)

     

     

     

     

     


     

    🔻 Destructuring

         전체의 개체 대신 특정 속성을 종속성으로 전달한다.

    // emailIsValid = emailState.isValid
      const { isValid: emailIsValid } = emailState;
      const { isValid: passwordIsValid } = passwordState;
    
    
      useEffect(() => {
        const identifier = setTimeout(() => {
          console.log("checkign form validity!");
          setFormIsValid(emailIsValid && passwordIsValid);
        }, 500);
    
    
        return () => {
          console.log("cleanup");
          clearTimeout(identifier);
        };
      }, [emailIsValid, passwordIsValid]);

     

     

     

     

     

     

     ex) 페이지 이동 2초뒤에 컴포넌트 사라지게하기

    더보기
    // 1. UI가 보이고 안보이고의 상태를 state로 저장한다.
    
    function Detail() {
      let [재고, 재고변경] = useState(true);
      
      
    // 2. state가 true일때만 UI가 보이게한다.
    {재고 === true ? (
      <div className="my-alert">
        <p>재고가 얼마 남지 않았습니다</p>
      </div>
     ) : null}
    // useEffect import해준다.
    import React, { useState, useEffect } from "react";
    
    
    2. setTimeout이용해서 2초뒤에 false로 바꿔준다.
      useEffect(() => {
        let 타이머 = setTimeout(() => {
          재고변경(false);
        }, 2000);
      };

     > 이렇게 해주면 컴포넌트가 업데이트될 때도 저 useEffect가 실행된다. 

       update될 때는 useEffect() 실행하지 말아주세요. 라는 코드를 추가한다.

     

     

     

     

    >  대괄호안에 state를 넣어서 '이 state가 변경 될 때만 업데이트로 치고 실행해라' 라는 명령 줄 수 있다.

       콤마로 state여러개 추가할 수 있다.

    // alert이라는 이름의 state가 변경될 때만 업데이트로 치고 실행해라.
    useEffect(()=>{
       let 타이머 = setTimeout(()=>{ alert변경(false) }, 2000);
    }, [ alert ]);

     

     

     

    > 빈 대괄호를 추가해준다. (여기에는 state를 넣을 수 있다.)

       조건을 안넣으면 컴포넌트 로드할때만 한번 실행한다.

    useEffect(()=>{
       let 타이머 = setTimeout(()=>{ alert변경(false) }, 2000);
    }, []);

     

     

     


     

     

     

     

     

     

    useReducer

     

     

     

     

    기본적으로 상태관리는 useState로하고 다음의 경우 reducer사용을 고려해본다.

    - 관리해야 할 state가 많아질 때 ( state 여러개를 결합해야할 때 )

    -  좀 더 복잡한 state updates 로직이 필요할 때 ( 다른 state에 의존하는 state를 update할 때 )

     

     

     

    const [state, dispatch] = useReducer(reducer, initialArg, init);

     

     

     

    reducer 기본 사용법

    - 기본 reducer함수 생성

    function reducer(state, action) {
      switch (action.type) {
        case "increment":
          return state + 1;
        case "decrement":
          return state - 1;
        default:
          throw new Error("unhandled action");
      }
    }

     

    -  cosnt [기본값, 액션작동] = useReducer(만든reducer함수, 초기값)

    function Counter () {
      const [number, dispatch] = useReducer(reducer, 0)
    }

     

    - (state를 썼다면 setState로 조정하던 부분에서) dispatch type 지정

    const onIncrease = () => {
      dispatch({
        type: "increment",
      });
    };
    
    const onDecrease = () => {
      dispatch({
        type: "decrement",
      });
    };

     

     

     

     

    useState   VS  useReducer

     

     

     

     

     

     

     

     

    반응형

    '• React' 카테고리의 다른 글

    [React] Formik / Yup  (0) 2021.11.22
    [React] Ajax - axios  (0) 2021.10.25
    [React] styled-components / SASS / CSS Module  (0) 2021.10.24
    [React] Router  (0) 2021.10.24
    [React] React hook basic  (0) 2021.10.21