TodoList get Todo detail하기

히진로그·2022년 9월 20일
0

mini-project

목록 보기
19/28
post-thumbnail

내가 어렵다고 생각한 단계, 투두 타이틀을 클릭하면 상세 내용을 보여주는 단계를
해치웠다✨ 사실 맞게 한 건지 모르겠는데, 일단 내가 생각한 대로 구현은 해냈다. 리팩토링 하면서 틀린 부분은 또 고쳐가는 거지 뭐 ㅎㅎ

우선 구현한 화면 먼저 보고 코드랑, 왜 그렇게 구현했는지 정리해보자👻

내가 구현하고 싶었던 것:

투두 제목 리스트에서 제목을 클릭하면 옆 화면에 해당하는 투두의 제목과 내용 그리고 수정, 삭제 버튼 띄우기

어떻게 구현했는지:

useReducer, Context api 사용해서 클릭된 제목의 글 id를 전역에서 관리함.
제목을 클릭할 때 클릭이벤트로 dispatch함수를 실행하여 초기 값을 null로 가지는 id값을 해당 글의 id값으로 업데이트함. 업데이트된 id값으로 axios 요청을 보냄

자세히는..?

TodoTitle에서 제목을 클릭하여 해당 투두의 id를 받아와서 TodoDetail 컴포넌트에서 id값을 이용해 투두의 상세 내용을 보여주려고 한다.
내가 구성한 컴포넌트의 구조는 위 그림과 같고, 투두 제목을 클릭하는 이벤트는 TodoTitle 컴포넌트에서 일어나고 그에 따른 반응은 TodoDetail 컴포넌트에서 일어나야 한다. 그리고 TodoDetail 컴포넌트에서는 제목을 클릭할 때 받아온 id값을 이용해 axios 요청을 보내야 한다. 즉 컴포넌트 간에 id값을 주고받아야 한다.
제일 처음에는 lifting state up도 생각했는데, 최근에 강의에서 배웠던 useReduce함수와 Context api를 사용한 상태 관리를 사용해보고 싶었다.

globalContext를 위한 새로운 폴더, 파일을 만들고 전역에서 사용할 state의 useReduce함수랑 context api를 만들었다.

const globalReducer = (state, action) => {
  switch (action.type) {
    case 'detail':
      return { ...state, id: action.payload };
    default:
      return state;
  }
};

const GlobalContextProvider = ({ children }) => {
  const [state, dispatch] = useReducer(globalReducer, {
    token: null,
    id: null,
  });

  return (
    <GlobalContext.Provider value={{ ...state, dispatch }}>
      {children}
    </GlobalContext.Provider>
  );
};

현재 todo상세 내용을 보여주는 TodoDetail 컴포넌트의 코드는 다음과 같다.

// TodoDetail 컴포넌트

export const TodoDetail = () => {
  const [title, setTitle] = useState('');
  const [detail, setDetail] = useState('');
  const { id } = useGlobalContext();
  const token = localStorage.getItem('token');

  const getTodoDetail = async () => {
    try {
      await axios
        .get(`http://localhost:8080/todos/${id}`, {
          headers: {
            Authorization: token,
          },
        })
        .then((result) => {
          setTitle(result.data.data.title);
          setDetail(result.data.data.content);
        });
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    id && getTodoDetail();
  }, [id]);

  return (
    <Detail>
      {id && (
        <>
          <h1>{title}</h1>
          <p>{detail}</p>
          <div>
            <button>EDIT</button>
            <button>DEL</button>
          </div>
        </>
      )}
    </Detail>
  );
};

id가 없으면 빈 화면을 보여주고, 타이틀을 클릭했을 때 dispatch 함수를 실행해서 id를 업데이트하고 해당 id의 글을 받아와서 보여준다.
dispatch함수를 실행하는 하는 부분은 TodoTitle 컴포넌트에 있다.

// TodoTitle 컴포넌트

  const getTodoIdHandler = (event) => {
    dispatch({ type: 'detail', payload: event.target.id });
  };

 return (
    <Title>
      {datas.length > 0 ? (
        datas.map((data) => {
          return (
            <li key={data.id} id={data.id} onClick={getTodoIdHandler}>
              {data.title}
            </li>
          );
        })
      ) : (
        <strong>there is no todo :(</strong>
      )}
    </Title>
  );

리스트에 클릭 메서드를 넣어 클릭하면 dispatch함수가 실행되도록 했다.

중간에 살짝 헤맸지만, 내가 생각한 대로 잘 구현해서 다행이다.

이제 todo 업데이트랑 삭제 기능이 남았다.ㅎㅎ😆
리팩토링 전까지 모든 기능 다 구현해보는 것이 오늘 목표니까! 천천히 또 집중해서 만들어봐야겠다!

0개의 댓글