[TIL/React] 2023/05/09

원민관·2023년 5월 9일
0

[TIL]

목록 보기
67/159
post-thumbnail

1. 설치

2. store 관련 셋팅

3. InputSection 관련 셋팅


4. TodoSection 관련 셋팅

CompleteSection

5. 나머지 기능 구현

<src/Components/InputSection.js>

import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { addTodo } from "../Reducer/reducer";

const inputArray = ["title", "subtitle", "desc"];

const InputSection = () => {
  const dispatch = useDispatch();
  const todo = useSelector((state) => state?.todo);

  const [inputValue, setInputValue] = useState({
    title: "",
    subtitle: "",
    desc: "",
    isDone: false,
    editMode: false,
  });

  const handleInputValue = (event) => {
    const { value, name } = event?.target;
    setInputValue((prev) => {
      return { ...prev, [name]: value };
    });
  };

  const handleAddClick = () => {
    dispatch(
      addTodo({
        ...inputValue,
        id: `${inputValue?.title}${inputValue?.subtitle}${inputValue?.desc}`,
      })
    );
    setInputValue({
      title: "",
      subtitle: "",
      desc: "",
      isDone: false,
      editMode: false,
    });
  };

  console.log({ inputValue, todo });
  return (
    <div>
      <h1>TodoList</h1>
      {inputArray?.map((elem, idx) => {
        return (
          <div key={idx}>
            <input
              name={elem}
              value={inputValue?.[elem]}
              onChange={handleInputValue}
            />
          </div>
        );
      })}

      <button onClick={handleAddClick}>Add</button>
    </div>
  );
};

export default InputSection;

<src/Components/TodoSection.js>

import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
  cancelTodo,
  completeTodo,
  deleteTodo,
  editTodo,
  saveTodo,
} from "../Reducer/reducer";

const TodoSection = () => {
  const todo = useSelector((state) => state?.todo);
  const dispatch = useDispatch();

  const [editValue, setEditValue] = useState({});

  const noCompleteArray = todo?.filter((todo) => todo?.isDone === false);
  const completeArray = todo?.filter((todo) => todo?.isDone === true);

  const handleEditValue = (event) => {
    const { value, name } = event?.target;
    setEditValue((prev) => {
      return { ...prev, [name]: value };
    });
  };

  const handleDeleteClick = (id) => {
    dispatch(deleteTodo(id));
  };

  const handleCompleteClick = (id) => {
    dispatch(completeTodo(id));
  };

  const handleEditClick = (id) => {
    dispatch(editTodo(id));
    let findValue = [...noCompleteArray]?.find((todo) => todo?.id === id);
    setEditValue(findValue);
  };

  const handleSaveClick = (id) => {
    dispatch(saveTodo(id, editValue));
  };

  const handleCancelClick = (id) => {
    dispatch(cancelTodo(id));
  };
  return (
    <div>
      <div>
        <h2>Todo Section</h2>
        <div>
          {noCompleteArray?.map((todo) => {
            return todo?.editMode ? (
              <div key={todo?.id}>
                <div>
                  <input
                    name="title"
                    value={editValue?.title}
                    onChange={handleEditValue}
                  />
                  <input
                    name="subtitle"
                    value={editValue?.subtitle}
                    onChange={handleEditValue}
                  />
                  <input
                    name="desc"
                    value={editValue?.desc}
                    onChange={handleEditValue}
                  />
                </div>
                <div>
                  <button onClick={() => handleSaveClick(todo?.id)}>
                    Save
                  </button>
                  <button onClick={() => handleCancelClick(todo?.id)}>
                    Cancel
                  </button>
                </div>
              </div>
            ) : (
              <div key={todo?.id}>
                <div>
                  <p>{todo?.title}</p>
                  <p>{todo?.subtitle}</p>
                  <p>{todo?.desc}</p>
                </div>
                <div>
                  <button onClick={() => handleDeleteClick(todo?.id)}>
                    Delete
                  </button>
                  <button onClick={() => handleCompleteClick(todo?.id)}>
                    Complete
                  </button>
                  <button onClick={() => handleEditClick(todo?.id)}>
                    Edit
                  </button>
                </div>
              </div>
            );
          })}
        </div>
      </div>
      <div>
        <h2>Complete Section</h2>
        <div>
          {completeArray?.map((todo) => {
            return (
              <div key={todo?.id}>
                <div>
                  <p>{todo?.title}</p>
                  <p>{todo?.subtitle}</p>
                  <p>{todo?.desc}</p>
                </div>
                <div>
                  <button onClick={() => handleDeleteClick(todo?.id)}>
                    Delete
                  </button>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
};

export default TodoSection;

<src/Reducer/reducer.js>

// action
const ADD_TODO = "ADD_TODO";
const DELETE_TODO = "DELETE_TODO";
const COMPLETE_TODO = "COMPLETE_TODO";
const EDIT_TODO = "EDIT_TODO";
const SAVE_TODO = "SAVE_TODO";
const CANCEL_TODO = "CANCEL_TODO";

// action Fn
export const addTodo = (todo) => ({ type: ADD_TODO, todo });
export const deleteTodo = (id) => ({ type: DELETE_TODO, id });
export const completeTodo = (id) => ({ type: COMPLETE_TODO, id });
export const editTodo = (id) => ({ type: EDIT_TODO, id });
export const saveTodo = (id, updatedTodo) => ({
  type: SAVE_TODO,
  id,
  updatedTodo,
});
export const cancelTodo = (id) => ({ type: CANCEL_TODO, id });

// initialState
const initialState = {
  todo: [],
};

// reducer
const reducer = (state = initialState, action) => {
  switch (action?.type) {
    case ADD_TODO:
      return { ...state, todo: [...state?.todo, action?.todo] };
    case DELETE_TODO:
      return {
        ...state,
        todo: [...state?.todo]?.filter((todo) => todo?.id !== action?.id),
      };
    case COMPLETE_TODO:
      return {
        ...state,
        todo: [...state?.todo]?.map((todo) =>
          todo?.id === action?.id ? { ...todo, isDone: true } : todo
        ),
      };
    case EDIT_TODO:
      return {
        ...state,
        todo: [...state?.todo]?.map((todo) =>
          todo?.id === action?.id ? { ...todo, editMode: true } : todo
        ),
      };
    case SAVE_TODO:
      return {
        ...state,
        todo: [...state?.todo]?.map((todo) =>
          todo?.id === action?.id
            ? { ...action?.updatedTodo, editMode: false }
            : todo
        ),
      };
    case CANCEL_TODO:
      return {
        ...state,
        todo: [...state?.todo]?.map((todo) =>
          todo?.id === action?.id ? { ...todo, editMode: false } : todo
        ),
      };
    default:
      return state;
  }
};

export default reducer;

<src/Reducer/store.js>

import { createStore } from "redux";
import reducer from "./reducer";

const store = createStore(reducer);

export default store;

<src/App.js>

import React from "react";
import InputSection from "./Components/InputSection";
import TodoSection from "./Components/TodoSection";

function App() {
  return (
    <>
      <InputSection />
      <TodoSection />
    </>
  );
}

export default App;

<src/index.js>

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import store from "./Reducer/store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
profile
Write a little every day, without hope, without despair ✍️

0개의 댓글