[Redux]react-redux Hooks

Hyoyoung Kim·2024년 2월 26일
0

React TIL

목록 보기
40/40

리덕스 스토어와 연동된 컨테이너 컴포넌트를 만들 때 connect 함수를 사용하는 대신 react-redux에서 제공하는 Hooks를 사용할 수 있습니다.

1. useSelector로 상태 조회하기

useSelector Hook을 사용하면 connect 함수를 사용하지 않고도 리덕스의 상태를 조회할 수 있습니다.

const 결과 = useSelector(상태 선택 함수)
import React from 'react';
import Counter from '../componenets/Counter';
import { decrease, increase } from '../modules/counter';
import { connect, useDispatch, useSelector } from 'react-redux';
//디스패치

const CounterContainer = ()=>{
    
    const number = useSelector(state=>state.counter.number);

    return(
        <Counter number={number}/>
    )
}

2. useDispatch를 사용하여 액션 디스패치하기

useDispatch는 컴포넌트 내부에서 스토어의 내장 함수 dispatch를 사용할 수 있게 해줍니다.

import React from 'react';
import Counter from '../componenets/Counter';
import { decrease, increase } from '../modules/counter';
import {useDispatch, useSelector } from 'react-redux';
//디스패치

const CounterContainer = ()=>{
    
    const number = useSelector(state=>state.counter.number);
    const dispatch =useDispatch()

    return(
        <Counter number={number} 
		onIncrease={()=>dispatch(increase())} 
    	onDecrease={()=>dispatch(decrease())}/>
    )
}

export default CounterContainer;
  • 위의 코드는 숫자가 바뀌어서 컴포넌트가 리렌더링될 때마다 onIncrease 함수와 onDecrease 함수가 새롭게 만들어지고 있습니다.
  • 컴포넌트 성능을 최적화해야 하는 상황이 온다면 useCallback으로 액션을 디스패치하는 함수를 감싸 주는 것이 좋습니다.
import React, { useCallback } from 'react';
import Counter from '../componenets/Counter';
import { decrease, increase } from '../modules/counter';
import { connect, useDispatch, useSelector } from 'react-redux';
//디스패치

const CounterContainer = ()=>{
    
    const number = useSelector(state=>state.counter.number);
    const dispatch =useDispatch()
    const onIncrease = useCallback(()=>dispatch(increase()),[dispatch])
    const onDecrease = useCallback(()=>dispatch(decrease()),[dispatch])

    return(
        <Counter number={number} onIncrease={onIncrease} onDecrease={onDecrease}/>
    )
}

export default CounterContainer;

3. useStore를 사용하여 리덕스 스토어 사용하기

  • useStore Hooks를 사용하면 컴포넌트 내부에서 리덕스 스토어 객체를 직접 사용할 수 있습니다.
  • useStore Hooks를 사용해야 하는 상황은 흔치 않습니다.

4. useActions 유틸 Hook을 만들어서 사용하기

  • 여러개의 액션을 사용해야 하는 경우 useActions 유틸 Hook을 사용해 코드를 훨씬 깔끔하게 정리하여 작성 할 수 있습니다.
// lib/useActions.js

import { bindActionCreators } from "redux";
import { useDispatch } from "react-redux";
import { useMemo } from "react";

export default function useActions(actions,deps){
    const dispatch = useDispatch();
    return useMemo(()=>{
        if(Array.isArray(actions)){
            return actions.map(a=> bindActionCreators(a,dispatch));
        }
        return bindActionCreators(actions,dispatch);
    },deps?[dispatch,...deps] :deps)
    
}
  • 위의 코드는 useActions Hook은 액션 생성 함수를 액션을 디스패치하는 함수로 변환해줍니다.
  • 액션 생성 함수를 사용하여 액션 객체를 만들고, 이를 스토어에 디스패치하는 작업을 해주는 함수를 자동으로 만들어줍니다.
  • useActions는 두가지 파라미터가 필요합니다. 첫번째 파라미터는 액션 생성함수로 이루어진 배열입니다.
  • 두번째 파라미터는 deps 배열이며, 이 배열 안에 들어 있는 원소가 바뀌면 액션을 디스패치하는 함수를 새로 만들게 됩니다.
//containers/TodoContainer.js

import Todos from '../componenets/Todos';
import { connect, useDispatch, useSelector } from 'react-redux';
import { changeInput,insert,remove,toggle } from '../modules/todos';
import { useCallback } from 'react';
import useActions from '../lib/useActions';


const TodosContainer = ()=>{
    const {input,todos} = useSelector(({todos})=>({
        input: todos.input,
        todos: todos.todos
    }))
    // const dispatch = useDispatch();
    // const onChangeInput = useCallback((input)=>dispatch(changeInput(input)),[dispatch])
    // const onInsert = useCallback((text)=>dispatch(insert(text)),[dispatch])
    // const onToggle = useCallback((id)=>dispatch(toggle(id)),[dispatch])
    // const onRemove = useCallback((id)=>dispatch(remove(id)),[dispatch])

    const [onChangeInput, onInsert, onToggle, onRemove] = useActions([changeInput,insert,toggle,remove],[])
    return(
        <Todos     
        input ={input}
        todos = {todos}
        onChangeInput ={onChangeInput}
        onInsert = {onInsert}
        onToggle ={onToggle}
        onRemove ={onRemove}/>
    )
}

export default TodosContainer;

💥 connect함수와 react-redux Hooks의 차이점

  • connect 함수를 사용하여 컨테이너 컴포넌트를 만들었을 경우, 해당 컨테이너 컴포넌트의 부모 컴포넌트가 리렌더링될 때 해당 컨테이너 컴포넌트의 props가 바뀌지 않았다면 리렌더링이 자동으로 방지되어 성능이 최적화됩니다.
  • 반면, useSelector를 사용하여 리덕스 상태를 조회했을때는 최적화 작업이 자동으로 이루어지지 않으므로, 성능 최적화를 위해 React.memo를 컨테이너 컴포넌트에 사용해주어야 합니다.

import Todos from '../componenets/Todos';
import {  useSelector } from 'react-redux';
import { changeInput,insert,remove,toggle } from '../modules/todos';
import React from 'react';
import useActions from '../lib/useActions';


const TodosContainer = ()=>{
	(...)
}

export default React.memo(TodosContainer);

0개의 댓글