히치키치

typescript-todo : createContext & useContext 작성 본문

typescript-todo

typescript-todo : createContext & useContext 작성

히치키치 2022. 8. 12. 19:03

💙 CreateContext

// /src/contexts/task-store.ts

import React, { createContext } from 'react';
import { Task } from '../types';


// 1. context 생성 : task가 원소인 리스트 (할 일들)

const TaskContext = createContext<
  [Task[], React.Dispatch<React.SetStateAction<Task[]>>]
>([[], () => {}]);
export default TaskContext;

💙 useContext 훅 : useTaskStore

// /src/hooks/use-task-store.ts

import useLocalStorage from './use-local-storage';
import React, { useState, useContext, useEffect } from 'react';
import { Task } from '../types';
import { shuffle } from 'lodash';
import { nanoid } from 'nanoid';
import TaskContext from '../contexts/task-store';

const useTaskStore = () => {
  
  // 1. useContext로 TaskContext 상태 사용
  const [tasks, setTasks] = useContext(TaskContext);

  // 2. FocusScreen에 띄울 할 일 id 설정
  // useState로 초기값 정의
  // filter 사용해 isComplete가 false로 구성된 task[] 만들고 그 중 첫번째 값의 id
  const [focusedTaskId, setFocusedTaskId] = useState<string | undefined>(
    tasks.filter((task) => !task.isComplete)[0]?.id
  );
  
  // 3. 2에서 정한 id에 해당하는 task를 tasks에서 find로 찾아서 값으로 설정
  const focusedTask = tasks.find((task) => task.id === focusedTaskId);
  
  // 4. task의 isComplete 여부를 update해 새로운 tasks 값 생성
  const updateTaskCompletion = (taskId: string, isComplete: boolean) => {
  // task의 id와 isComplete를 인자로 받음
    setTasks((tasks) =>
      tasks.map((task) => { 
      // tasks 배열을 map으로 돌면서
        if (task.id === taskId) { 
        // 완료 여부가 변경된 task인 경우
          return { ...task, isComplete }; 
          //완료 여부를 update 해서 해당 task 요소를 반환
        } else { // 완료 여부가 변경된 task가 아닌 경우
          return task;
          // 해당 task 요소 그대로 반환
        }
      })
    );
  };

  useEffect(() => {
    if (focusedTask?.isComplete) {
      setFocusedTaskId(tasks.filter((task) => !task.isComplete)[0]?.id);
    }
  }, [tasks, focusedTask]);

  // 5. filter를 통해 아직 완료되지 않은 할일 배열 생성
  const shuffleFocusedTask = () => {
  	// filter를 통해 아직 완료되지 않은 할 일로만 구성된 배열 생성
    // loadash 라이브러리의 shuffle 활용해 해당 배열의 순서를 바꿈
    // 순서가 바뀐 배열의 첫번째 할 일을 focusScreen에 띄울 값으로 지정
    setFocusedTaskId(shuffle(tasks.filter((task) => !task.isComplete))[0]?.id);
  };
  
  // 6. Pick 사용해 task 속성 중 label만 타입 검증
  const addTask = (task: Pick<Task, 'label'>) => {
    const id = nanoid();
    setTasks((tasks) => [
      ...tasks, // 기존의 할 일들 갱신
      { id: id, label: task.label, isComplete: false }, // 새로운 할일 목록에 추가
    ]);
    if (!focusedTaskId) { 
    //만약 최초로 task가 추가되어 focusScreen에 뜰 task가 지정되지 않은 상태인 경우
      setFocusedTaskId(id); // 추가해... 
    }
  };

  const api = {
    addTask,
    focusedTask,
    tasks,
    setTasks,
    updateTaskCompletion,
    shuffleFocusedTask,
  };

  return api;
};

export default useTaskStore;

 

Comments