본문 바로가기

JavaScript/Redux

Redux - react-redux

1. react-redux?

  • 리액트 노드 패키지로써, 리액트에 리덕스를 좀 더 사용하기 편리하도록 만든 라이브러리입니다.
  • 기존 리덕스와 마찬가지로, 스토어 > 컴포넌트 > 액션 > 리듀서 > 스토어의 과정을 통해  상태를 변경합니다.
  • 차이점connect라는 함수가 사용된다는 점입니다.

 

2. 기본 사용법

아래 예제는 간단히 추가 버튼을 누르면, TodoList에 값이 추가되어 보여지는 앱을 만드는 예제입니다.

 

먼저, react-redux를 설치합니다.

$ npm i react-redux

 

connect 함수를 사용해 TodoList 컴포넌트를 생성합니다.

import { connect } from 'react-redux';

function TodoList({ todos }) {
  return (
    <>
      <ul>
        {todos.map((todo, index) => {
          return <li>{todo}</li>;
        })}
      </ul>
    </>
  )
}

const mapStateToProps = (state) => {
  return {
    todos: state
  };
}

const mapDispatchToProps = (dispatch) => {
  return {};
};

const TodoListContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList);

export default TodoListContainer;
  • connect(mapStateToProps, mapDispatchToProps)(Component) : 컴포넌트와 리덕스를 연결해주는 HOC 함수입니다. 인자로 전달한 값이 컴포넌트 props로 전달됩니다. connect 함수의 반환값은 함수이므로 괄호가 두 번 사용됩니다.
  • mapStateToProps : 컴포넌트로 전달할 리덕스의 State입니다. 현재 State를 인자로 받아서 반환하면, 컴포넌트로 State를 전달해줍니다.
  • mapDispatchToProps : 컴포넌트로 전달할 리덕스의 Dispatch 함수입니다. Dispatch를 인자로 받아서 컴포넌트로 전달해 줍니다.

 

이제 상태 관련 로직과 뷰 부분이 분리가 된 모습을 볼 수 있습니다.

마찬가지로, TodoList에 등록할 값을 입력할 수 있는 TodoForm 컴포넌트를 생성하겠습니다.

 import { useRef } from 'react';
 import { connect } from 'react-redux';
 import addTodo from '../redux/actions/actions';
 
 function TodoForm({ add }) {
  const inputRef = useRef();

  return (
    <>
      <input ref={inputRef} />
      <button onClick={click}>추가</button>
    <>
  );

  function click() {
   add(inputRef.current.value);
  }
}

 export default connect (
   (state) => ({}),
   (dispatch) => ({
     add: (text) => {
       dispatch(addTodo(text));
     }
   })
 )(TodoForm);
  • addTodo : 리덕스 세팅 시 만들었던 action입니다. react-redux의 대략적인 흐름만 파악하기 위해 코드는 미포함입니다.

 

이제 App.js에 위 컴포넌트들을 넣어주고

import './App.css';
import TodoList from './components/TodoList';
import TodoForm from './components/TodoForm';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <TodoForm />
        <TodoList />
      </header>
    </div>
  );
}

export default App;

 

index.js에 react-redux의 Provider를 사용해 리덕스 store를 전달해주면 끝입니다.

...
import store from './redux/store';
import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App /> 
    </Provider>
  </React.StrictMode>
);

...
  • Provider : react-redux 라이브러리에 내장돼있는, store를 쉽게 연동할 수 있도록 도와주는 컴포넌트입니다. 리액트의 Context와 비슷한 개념입니다.

 

3.훅으로 더 심플하게 만들기

 

useSelector

  • useSelector는 리덕스의 상태값을 조회하기 위한 훅으로써, connect로 조회하는 것보다 더 간결하게 만들 수 있도록 해줍니다.

 

위 예제의 FormList의 경우 아래와 같이 바꿀 수 있습니다.

import { useSelector } from 'react-redux';

function TodoList({ todos }) {
  return (
    <>
      <ul>
        {todos.map((todo, index) => {
          return <li>{todo}</li>;
        })}
      </ul>
    </>
  );
}

function TodoListContainer() {
  const todos = useSelector((state) => state);
  return <TodoList todos={todos} />;
}

export default TodoListContainer;

 

useDispatch

  • 리덕스의 dispatch 값을 조회하기 위한 훅입니다.

 

위 예제의 TodoForm의 경우 아래처럼 바꿀 수 있습니다.

import { useDispatch } from 'react-redux';
import TodoForm from '../components/TodoForm';
import addTodo from '../redux/actions/actions'; 
import { useRef } from 'react';
 
function TodoForm({ add }) {
  const inputRef = useRef();

  return (
    <>
    <input ref={inputRef} />
    <button onClick={click}>추가</button>
    </>
  );

  function click() {
   add(inputRef.current.value);
  }
}

export default function TodoFormContainer() {
  const dispatch = useDispatch();

  function add(text) {
    dispatch(addTodo(text));
  }

  return <TodoForm add={add} />;
}

 

이렇게 전역적으로 store와 dispatch를 조회할 수 있기 때문에, 기존 리액트의 Context API 또는 props로 store를 전달했을 때보다 편리하고 코드가 심플해지는 걸 알 수 있습니다.

'JavaScript > Redux' 카테고리의 다른 글

Redux - 고급 사용법  (0) 2022.04.20
Redux - 사용해보기  (0) 2022.03.19
Redux - Basic  (0) 2022.03.16