sparta TIL

24.05.29 Redux 4,5,6

hr7 2024. 5. 26. 05:34

[ Redux 4 - Redux 기반 TodoList 만들기 ]

 

∙ 폴더구조

∙ 코드도 강의 따라서 그대로 

 

 

 

 

 

 

 

 

 

// App.jsx
import AddForm from "./components/AddForm";
import TodoList from "./components/TodoList";

const App = () => {
  return (
    <div>
      <h1>Todo</h1>
      <AddForm />
      <TodoList />
    </div>
  );
};
export default App;
// AddForm.jsx
import { useState } from "react";
import { useDispatch } from "react-redux";
import { addTodo } from "../redux/modules/todos";

const AddForm = () => {
  const [todo, setTodo] = useState("");
  const dispatch = useDispatch();

  return (
    <div>
      <input
        type="text"
        value={todo}
        onChange={(e) => {
          setTodo(e.target.value);
        }}
      />
      <button
        onClick={() => {
          dispatch(
            addTodo({
              id: new Date().getTime(),
              title: todo,
            })
          );
        }}
      >
        추가
      </button>
    </div>
  );
};

export default AddForm;
// TodoList.jsx
import { useSelector } from "react-redux";

const TodoList = () => {
  const todos = useSelector((state) => state.todos);
  console.log(todos);
  return (
    <div>
      {todos.map(function (todo) {
        return <div key={todo.id}>{todo.title} </div>;
      })}
    </div>
  );
};

export default TodoList;
// configStore.js
import { combineReducers } from "redux";
import todos from "../modules/todos";
import { createStore } from "redux";

const rootReducer = combineReducers({
  todos: todos,
});

const store = createStore(rootReducer);
export default store;
// main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import { Provider } from "react-redux";
import store from "./redux/config/configStore.js";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);
// todos.js
// action value
const ADD_TODO = "ADD_TODO";

// action creator 만들어서 export(컴포넌트에서 사용할 수 있도록)
export const addTodo = (payload) => {
  return {
    type: ADD_TODO,
    payload: payload,
  };
};

// state init
const initialState = [
  {
    id: 1,
    title: "react를 배워봅시다.",
  },
  {
    id: 2,
    title: "redux를 배워봅시다.",
  },
];

const todos = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, action.payload];

    default:
      return state;
  }
};

export default todos;

[ Redux 5 - RTK(Redux ToolKit)]

(Redux ToolKit)이 뭘까?

redux의 코드는 더 간략히, 더 편하게 쓰기 위한 기능들을 흡수해 만든 것 👉🏻 리덕스를 개량한 것  

 

$ yarn add react-redux @reduxjs/toolkit  으로 설치

✔️ 이젠 modules안쓰고 slices로 사용한다.

 

 

 

 

 

 

 

 

▼ 툴킷 사용한 수정코드

counter.js코드와 동일한 코드를 툴킷사용하여 새롭게 짠 것
툴킷 사용한 리듀서 만들기 1
툴킷 사용해서 만들 리듀서 적용하기 2
slices파일로 import바꿔줌


[ Redux Devtools ]

현재 프로젝트의 state 상태라던가, 어떤 액션이 일어났을 때 그 액션이 무엇이고, 그것으로 인해 state가 어떻게 변경되었는지 등 리덕스를 사용하여 개발할 때 아주 편리하게 사용할 수 있다.

오.. .지금은 잘 모르겠지만, 쓸 날이 오겠지. 일단 설치


[ Flux 패턴 ]

Facebook에 의해 개발된 애플리케이션 아키텍처로, 주로 React와 함께 사용되며 데이터의 단방향 흐름을 강조한다.

Flux 아키텍처는 다음 네 가지 주요 구성 요소로 이루어져 있다.

 

1. Dispatcher: 애플리케이션 내 모든 데이터 흐름을 관리하는 중앙 허브 역할을 한다. 액션들이 발생하면 디스패처를 통해 스토어로 전달

2. Stores: 애플리케이션의 상태(데이터)와 로직을 보유한다. 스토어는 디스패처를 통해 전달된 액션에 반응하여 상태를 변경하고, 변경 사항을 뷰에 알림

3. Actions: 상태 변화를 일으킬 때 사용하는 간단한 객체이며 사용자 인터페이스에서 발생한 사용자의 행동을 액션으로 표현하고, 이를 디스패처를 통해 스토어로 전달한다.

4. Views (React Components): 사용자 인터페이스를 구성하는 React 컴포넌트들로 스토어에서 상태가 변하면, 뷰는 이를 반영하여 사용자 인터페이스를 업데이트한다.

 

Ducks - Redux 코드의 구조를 단순화하는 데 초점

Flux - 애플리케이션의 데이터 흐름을 체계화하는 데 중점

( Ducks 패턴과 Flux 패턴은 서로 다른 측면에 초점을 맞추고 있지만, 그 근본적인 목적은 모두 애플리케이션의 상태 관리와 데이터 흐름의 체계를 잡는 것이다. 특히 Redux를 사용하는 React 애플리케이션에서 이 둘은 함께 사용될 수 있다. )

https://bestalign.github.io/translation/cartoon-guide-to-flux/

 

Flux로의 카툰 안내서

원문: https://medium.com/code-cartoons/a-cartoon-guide-to-flux-6157355ab207 Flux…

bestalign.github.io

https://taegon.kim/archives/5288

 

Flux와 Redux

이 글에서는 Facebook에서 React와 함께 소개한 Flux 아키텍처에 대해 알아보고 Flux를 구현한 Redux 라이브러리를 살펴본 후 이를 적용한 간단한 React 애플리케이션을 작성해보겠다. 본문에 사용된 코

taegon.kim


[ Redux 6 - [실습] RTK 기반 TodoList 고도화 ]

 

폴더 재구성 (slices)

 

 

 

 

 

 

 

 

 

▼ todos.js → todosSlice.js로 RTK사용 재구성

// todosSlice.js
import { createSlice } from "@reduxjs/toolkit";

// state init
const initialState = [
  {
    id: 1,
    title: "react를 배워봅시다.",
  },
  {
    id: 2,
    title: "redux를 배워봅시다.",
  },
];

const todosSlice = createSlice({
  name: "todos",
  initialState,
  reducers: {
    addTodo: (state, action) => {
      return [...state, action.payload];
    },
  },
});
export const { addTodo } = todosSlice.actions;
export default todosSlice.reducer;

configStore.js RTK사용 수정

// configStore.js
import { configureStore } from "@reduxjs/toolkit";
import todosSlice from "../slices/todosSlice";

const store = configureStore({
  reducer: {
    todos: todosSlice,
  },
});

export default store;

AddForm.jsx import 수정

// AddForm.jsx
import { addTodo } from "../redux/slices/todosSlice";
// import { addTodo } from "../redux/modules/todos";

자바스크립트 베이직 과제 - todoList

import { useState } from "react";
import { v4 as uuidv4 } from "uuid";

function App() {
  const [input, setInput] = useState("");
  const [todos, setTodos] = useState([
    {
      id: 1,
      text: "베이직과제",
      completed: true,
    },
    {
      id: 2,
      text: "제출하기",
      completed: false,
    },
  ]);

  const handleInput = (e) => {
    setInput(e.target.value);
  };

  const handleAddTodo = (e) => {
    e.preventDefault();
    if (!input.trim()) return;
    const newTodo = {
      id: uuidv4(),
      text: input,
      completed: false,
    };
    setTodos([...todos, newTodo]);
    setInput("");
  };

  const handleDelete = (id) => {
    setTodos(todos.filter((todo) => todo.id !== id));
  };

  const handleToggle = (id) => {
    setTodos(
      todos.map((todo) =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    );
  };

  return (
    <div>
      <h1>할 일 목록</h1>
      <form onSubmit={handleAddTodo}>
        <input
          type="text"
          placeholder="할 일을 추가하세요"
          value={input}
          onChange={handleInput}
        />
        <button type="submit">추가</button>
      </form>

      <ul>
        {todos.map((todo) => (
          <li
            key={todo.id}
            style={{ textDecoration: todo.completed ? "line-through" : "none" }}
          >
            {todo.text}
            <button
              onClick={() => {
                handleToggle(todo.id);
              }}
            >
              {todo.completed ? "취소" : "완료"}
            </button>
            <button
              onClick={() => {
                handleDelete(todo.id);
              }}
            >
              삭제
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App;