Front-End

vsoghlv@naver.com

React.js 리덕스 리액트에서 구현하기

리덕스 기본 모듈 만들기에서 만든 모듈들을 이용해 여러가지 기능들을 구현해본다.

카운터 구현하기

프리젠테이셔널 컴포넌트

프리젠테이셔널 컴포넌트를 만들건데 프리젠테이셔널 컴포넌트란, 리덕스 스토어에 직접 접근하지 않고 필요한 값 또는 함수를 props 로 받아와서 사용하는 컴포넌트이다.

프리젠테이셔널 컴포넌트는 주로 UI 를 선언하는 것에 집중하고, 필요한 값, 함수를 props로 받아와 사용한다.

먼저 components 폴더를 만들고 새로운 파일을 작성한다.

//components/Counter.js
import React from "react";

function Counter({ number, diff, onIncrease, onDecrease, onSetDiff }) {
  const onChange = (e) => {
    onSetDiff(parseInt(e.target.value, 10));
  };
  return (
    <div>
      <h1>{number}</h1>
      <div>
        <input type="number" value={diff} onChange={onChange} />
        <button onClick={onIncrease}>+</button>
        <button onClick={onDecrease}>-</button>
      </div>
    </div>
  );
}

export default Counter;

컨데이너 컴포넌트

컨테이너 컴포넌트란 리덕스 스토어의 상태 조회, 액션 디스패치를 할 수 있는 컴포넌트를 의미하는데 HTML 태그들을 사용하지 않고 프리젠테이셔널 컴포넌트들을 불러와서 사용한다.

리덕스 스토어를 조회하기 위해서는 useSelector 를 사용하는데 이때 파라미터로 받는 statestore.getState() 함수에서 반환하는 객체와 동일하다.

dispatch 를 사용하기 위해서는 useDispatch 를 사용한다.

//containers/CounterContainers.js
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import Counter from "../components/Counter";
import { decrease, increase, setDiff } from "../modules/counter";

function CounterContainers() {
  //상태조회를 위한 함수
  //state = store.getState() 와 결과물 동일, 즉 현재의 상태
  const { number, diff } = useSelector((state) => ({
    number: state.counter.number,
    diff: state.counter.diff,
  }));
  const dispatch = useDispatch();

  //counter.js 에서 작성한 액션생성함수로 dispatch
  //함수를 만들어 호출하면 액션을 만들고 이를 디스패치 한다.
  const onIncrease = () => dispatch(increase());
  const onDecrease = () => dispatch(decrease());
  const onSetDiff = (diff) => dispatch(setDiff(diff));

  //만든것들을 전부 Counter 에 전달해주면 된다.
  return (
    <Counter
      number={number}
      diff={diff}
      onIncrease={onIncrease}
      onDecrease={onDecrease}
      onSetDiff={onSetDiff}
    ></Counter>
  );
}

export default CounterContainers;

할일목록(todos) 구현하기

프리젠테이셔널 컴포넌트

세가지의 프리젠테이셔널 컴포넌트를 만들건데

  1. TodoItem(하나의 할일 목록)
  2. TodoList(TodoItem 을 보여주는 리스트)
  3. Todos(TodoList 와 새로운 목록 추가하는 폼)

세가지다.

//components/Todos.js
import React, { useState } from "react";

const TodoItem = React.memo(function TodoItem({ todo, onToggle }) {
  //todo = todos 모듈안의 state 객체
  return (
    <li
      style=
      onClick={() => onToggle(todo.id)}
    >
      {todo.text}
      {todo.done}
    </li>
  );
});

const TodoList = React.memo(function TodoList({ todos, onToggle }) {
  return (
    <ul>
      {todos.map((todo) => (
        //키값 잊지 말것
        <TodoItem key={todo.id} todo={todo} onToggle={onToggle}></TodoItem>
      ))}
    </ul>
  );
});

function Todos({ todos, onCreate, onToggle }) {
  //리덕스를 사용한다고 모든 상태관리를 리덕스에서 할 필요는 없다.
  const [text, setText] = useState("");
  const onChange = (e) => setText(e.target.value);
  const onSubmit = (e) => {
    e.preventDefault();
    onCreate(text);
    setText("");
  };

  //목록을 추가하기 위한 폼과 TodoList
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input
          type="text"
          value={text}
          onChange={onChange}
          placeholder="할 일을 입력하세요"
        />
        <button type="submit">등록</button>
      </form>
      <TodoList todos={todos} onToggle={onToggle}></TodoList>
    </div>
  );
}

export default React.memo(Todos);

React.memo 를 사용해 최적화 작업을 해줬다.

컨데이너 컴포넌트

//containers/TodosContainer.js
import React, { useCallback } from "react";
import { useSelector, useDispatch } from "react-redux";
import Todos from "../components/Todos";
import { addTodo, toggleTodo } from "../modules/todos";

function TodosContainers() {
  const todos = useSelector((state) => state.todos);
  const dispatch = useDispatch();

  //useCallback 으로 최적화
  const onCreate = useCallback((text) => dispatch(addTodo(text)), [dispatch]);
  const onToggle = useCallback((id) => dispatch(toggleTodo(id)), [dispatch]);

  return <Todos todos={todos} onCreate={onCreate} onToggle={onToggle}></Todos>;
}

export default TodosContainers;

0


  • ㅇㄴㅁㄴㅇㅁ
  • ㅇㄴㅁㅇㄴㅁ
  • ㅈㅂㄷㅈㅂ
  • ㅀㄷㅈㅎㄱ

잘 작동된다.