React(2)

원동환·2021년 9월 4일
0

React Hooks

useEffect

  • 가장 많이 널리쓰이는 훅중에 하나로 잘 못 구현되었을때 가장 많이 문제를 일으키기도 하는 훅이다
    useEffect(() => {
    })
  • 기본적인 useEffect의 형태로 뒤에 deps가 없이 실행할경우 렌더링될때마다 매번 실행이 된다.
      useEffect(() => {
      }, [])
  • deps를 비워둔채로 선언을 하게 되면 컴포넌트가 처음 마운트 될때에만 실행이된다.
    useEffect(()=>{
    }, [value])
  • deps안에 값을 넣은채로 실행을 하면 deps안의 값이 바뀔때마다 실행이 된다. useEffect의 경우 deps를 잘 이용하는 것이 제일 중요한데 deps의 값에 의존해서 안의 함수들이 실행이 되는 구조라서
    안에서 뭔가를 구현했을경우 꼭 그에 맞는 값을 배열안에 추가 해주는 것이 중요하다. 추가를 하지않고 그냥 비워두거나 다른 값을 넣게 될 경우 컴포넌트 내부에선 값이 바꼈지만 useEffect 안의 값이 바뀌지
    않은채로 있을 수도 있다.

useState

  • 불변성을 유지하기 위해 많이 쓰는 훅이다.

    const [text, setText] = useState();
    
    useEffect(() => {
        setText("useState!!!")
    }, [text])

    이런방식으로 많이 쓰이고 불러온 데이터들을 가공해야 할 경우 데이터를 useState안에 담아서 새로 가공을 해서 쓰는 경우도 있다.

useMemo

  • 불필요할때에도 컴포넌트를 호출해서 자원이 낭비 되는것을 막기위해 쓰며 이전에 계산한 값을 재사용하는 훅이다.
      const text = useMemo(() => 
        function(), [])
    첫번째 파라미터에는 어떤연산을 할지 정의하는 함수를 넣어주고 두번째에는 deps배열을 넣어주면 된다. 위의 배열안에 넣은 값이 바뀔때만 등록한 함수를 호출해서 값을 연산하고 값이 바뀌지 않을경우에는
    이전 연산의 값을 그대로 재사용하게 되는 구조이다.

useCallback

  • useMemo와 비슷한 훅으로 useMemo의 경우 결과값을 재사용하지만 useCallback은 특정 함수를 새로 만들지 않고 재사용하고 싶을때 사용한다.
    const Remove = useCallback(id => {
      setUsers(users.filter(user => user.id !==id));
    }, [users]);
    함수 안에서 사용하는 상태 혹은 props가 있을경우 usecallback은 deps배열안에 무조건 포함을 시켜야한다. useCallback의 경우는 바로 최적화를 한다기 보다는 컴포넌트 렌더링 최적화를 같이 해야만
    성능이 최적화된다.

useReducer

  • useState사용하는 것 대신에 useReducer를 사용할 수 있고 이 훅 함수를 이용할 경우에는 컴포넌트의 상태업데이트 로직에서 컴포넌트에서 분리하고 컴포넌트 바깥에다가도 작성할 수 있다.
      function reducer(state, action){
        생략
      }
      function Counter(){
        const [number, dispatch] = useReducer(reducer, 0);
        return(~~~)
      }
    이런식으로 counter컴포넌트안에서 쓸 값들을 밖에서 action을 정의하고 쓸수 있는 것이다.

Redux Thunk

  • 리덕스의 미들웨어로 비동기작업을 처리할때 많이 사용하며 액션객체가 아닌 함수를 디스패치해서 쓸 수 있다. redux에서 thunk함수를 쓸려면
    먼저 redux-thunK 패키지를 설치하고 applyMiddlewares에 적용을 해야한다 그리고 기존의 액션타입을 생성하고 짜는 redux구조로 코드를 구현해보면

      const INCREASE = 'INCREASE';
      
      export const increase = () => ({ type: INCREASE});
      
      export const increaseAsync = () => dispatch => {
        setTimeout(() => dispatch(increase()), 1000);
        };
        
        export default function couter(state = initailState, action) {
        //reducer정의
        }

    이런식으로 thunk 함수를 정의하고

    import {increaseAsync} from "경로";
    
    const Increase = () => {
      dispatch(increaseAsync());
    }

    와 같이 컴포넌트에서 바로 함수를 불러서 디스패치를 할 수 있게된다.

  • ReduxToolkit createAsyncThunk + createSlice + extraReducer
    이번 프로젝트에서 리덕스 스토어에 상태를 업데이트 할때 쓰던 조합이다.

    export const getAllBeer = createAsyncThunk(
      "beer/getAllBeer",
      async (data, thunkAPI) => {
    
        const response = await axiosInstance.get(`/api/beer/list/${data}`);
    
        return response.data;
      }
    );

    이렇게 thunk를 써서 함수를 바로 디스패치 한다음 서버에 데이터 요청을 하고 받은 response.data를 action.payload의 변수안에 보낸다

    export const beerSlice = createSlice({
    name: "beer",
    initialState,
    extraReducers: (builder) =>
      builder
        .addCase(getAllBeer.fulfilled, (state, action) => {
            state.beerList = action.payload;
        })
        .addMatcher(
          (action) => {
            return action.type.includes("/pending");
          },
          (state, action) => {
            state.isLoading = true;
            state.isDone = false;
            state.isError = null;
          }
        )
        .addMatcher(
          (action) => {
            return action.type.includes("/fulfilled");
          },
          (state, action) => {
            state.isLoading = false;
            state.isDone = true;
          }
        )
        .addMatcher(
          (action) => {
            return action.type.includes("/rejected");
          },
          (state, action) => {
            state.isLoading = false;
            state.isError = action.error;
            console.log(action.error);
          }
        ),
    });

    여기서 상태반영을 하고 pending, fulfilled, rejected의 상태를 통합으로 관리해줬다. 에러가 발생할 경우 에러를 띄우고 fullfilled되면 state.isDone을 true로 바꾸는 방식으로 통합해서 관리해줬다.
    그리고 컴포넌트단에서는 원래 thunk함수를 쓰듯이 함수를 import해와서 바로 디스패치를 해서 사용하면 된다.

    reselect

    마찬가지로 상태관리를 위한 라이브러리로 reduxjs/toolkit에서는 reselect를 별도의 설치없이 바로 사용할수 있다.

    const beer = useSelector((state) => state.beer.beerList)

    기존의 useSelector는 이런 식으로 스토어의 데이터를 컴포넌트에서 핸들링해서 사용할 수 있으나 컴포넌트가 리렌더링 될때마다 함수가 재실행되는 낭비가 있다
    그래서 reselect를 이용하게 되면 reduxd store값을 가져와서 계산을 해서 redux가 적은양의 데이터만 가지고 있게 도와준다. 그리고 메모이징되기 때문에 재계산 방지에 효율적이다.

    const beer_One = (state) => state.beer.beerOne;
    
    export const oneBeer = createSelector(beer_One, beer_One => {
    return beer_One;
    }); // 맥주 1개데이터 

    기본적인 예시이고 state에서 필요한 부분을 가져오는 역할을 하고 그 다음 인자인 함수에서는 inputSelectors에서 반환된 값을 인자로 받아서 수행을 하는데 inputSelector의 값이 바뀌지 않을경우는
    저장된 cache값을 사용하여 불필요한 재계산을 하지 않도록 도와준다.

profile
Mojittoba

0개의 댓글