항해하다/항해 - 4주차

[항해99 4주차] - Redux 개인과제 (2) [코드 뜯어보기]

위르겐 2022. 8. 3. 16:35

 

 

Redux 투두리스트 

코드 하나하나 뜯어보자

 

기나긴 여정이 되겠지만

내가 왜 이런식으로 코드를 짰는지

복기할 수 있기 때문에

귀찮음을 감수할만한 충분한 가치가 있는 시간이라고 생각한다.

 

 

<App.js>

const App = () => {

  return (

    <Routes>
      <Route path="/" element={<TodoContainer/>}/>
      <Route path="/detail/:id" element={<Detail/>}/>
    </Routes>
  )
}

 

상세페이지 기능을 넣기전까지만해도

Route가 필요없었기 때문에

이런모양은 아니었지만

App.js를 이렇게 짜게된 건 원인이 아닌 

필요에의한 결과라고 보면 될 것같다.

 

Route로 경로를 설정해준 후 컴포넌트를 넣어준다.

 

그럼 URL에 위와같이 입력했을 때 해당 페이지로 이동할 수 있게된다.

 

단순 "/"경로는 메인페이지를 뜻하며

처음 실행될 때 보이는화면이 TodoContainer라는 컴포넌트가 보여지게 된다.

 

 

/detail/:id 는 

콜론뒤에 임의로 지정해줄 수 있지만

리스트 각각에 해당하는 id를 넣어주기 위함이었다.

 

 

 

 

<TodoContainer.js>

 

const TodosContainer = () => {


  return  (

    <>
    <GlobalStyle/>
    <LayoutDiv>
    <TodoContainer>
      <TodoForm/>
      <TodoList/>
    </TodoContainer>
    </LayoutDiv>
    </>
  )
}

export default TodosContainer;

 

 

<TodoForm>컴포넌트와 

<TodoList>컴포넌트 외에는 전부 styled 컴포넌트이기 때문에

생략하고

 

<TodoForm>컴포넌트를 봐보자.

 

 

const TodoForm = () => {



  const [title, setTitle] = useState("")
  const [content, setContent] = useState("")
  const dispatch = useDispatch();
  const onCreate = (title, content) => dispatch(addTodo(title, content));


  const onChange = e => {
    e.target.name === 'title' ? setTitle(e.target.value) : setContent(e.target.value)
  }

  const onClick = () => {
    if ( title !== '' && content !== '') {
      onCreate(title, content);
      setTitle('');
      setContent('');
    }
  }


  return  (
    <>
    <FormComtainer>
      <h1 style={{marginRight:"50px"}}>Todo!</h1>
      <FormItems>
        <h2>제목</h2>
        <TodoInput name="title" onChange={onChange} value={title}></TodoInput>
        <h2>내용</h2>
        <TodoInput name="content" onChange={onChange} value={content}></TodoInput>
        <TodoButton onClick={onClick} type="button">추가하기</TodoButton>
      </FormItems>
    </FormComtainer>
    </>
  )
}
export default TodoForm;

 

 

 

title과 content를 state로 지정해준 뒤 

input태그 두개에 속성으로 지정된

value={}에

넣어준다.

 

 

onChange함수에서는 조금 발칙한 상상을 해봤는데

input태그 두개의 name속성을 이용해

e.target.name이 'title'인 경우 

title에 e.target.value를 넣어주고

거짓인 경우 content에 e.target.value를 넣어줬다

 

onChange함수하나로 두 input태그를 제어할 수 있어 좋지만

인풋태그가 3개 이상이 될 경우엔

삼항연산을 중첩하든가 

조건문이 추가되어 확장성이 안좋아

useReducer를 사용해보라는 기술매니저님의 명을 받들어

다시 도전해보려고 한다.

 

 

 

onClick함수엔 

title과 content를 onCreate함수에 파라미터로 넣고 실행한다.

그 후 title과 content를 빈값으로 바꿔주는데

이 부분도 Reducer를 사용해서 깔끔하게 짤 수 있다고 하셨다.

 

꼭 사용해봐야겠다.

 

 

 

추가하기버튼을 onClick할 경우

실행되는 onCreate함수는 리덕스 스토어에 변경을 요청하는 dispatch가 포함된다.

 

 

이 부분은 store.js를 다룰 때 다시 살펴보자!

 

 

 

 

<TodoList.js>

const TodoList = () => {
  const state = useSelector((state) => state.todo.todo_1);
  const working_list = state.filter((todo) => todo.isDone === false).map((todo, i) => <TodoItem todo={todo} key={todo.id}></TodoItem>);
  const done_list = state.filter((todo) => todo.isDone === true).map((todo, i) => <TodoItem todo={todo} key={todo.id}></TodoItem>);
  return (
    <>
      <StH1>Working!!🔥🔥🔥</StH1>
      <StList>{working_list}</StList>
      <StH1>Done✔✔✔</StH1>
      <StList>{done_list}</StList>
    </>
  );
};

 

 

<TodoList.js>는

isDone이 false인 것과 true인 객체가

각각 다른곳에 배치되어 렌더링되게 한다.

 

 

 

 const state = useSelector((state) => state.todo.todo_1);
  const working_list = state.filter((todo) => todo.isDone === false).map((todo, i) => <TodoItem todo={todo} key={todo.id}></TodoItem>);
  const done_list = state.filter((todo) => todo.isDone === true).map((todo, i) => <TodoItem todo={todo} key={todo.id}></TodoItem>);

 

 

리덕스 스토어에서 

객체가 추가된 배열들을 받아온 후 

 

각각 filter함수를 돌려 true인것과 false인 것을 분리한다.

 

 

그 분리된 배열을 바로 뒤에 map함수를 써 

<TodoItem>컴포넌트를 뿌려준다.

 

 

콜백함수 두개를 연속으로 쓰고

그 코드를 이해하는 날이오다니 정말 감개무량하다... ㅠ

 

 

 

 map함수의 인자를 이용해

각각의 <TodoItem>컴포넌트에 props로 보내준다.

 

 

그리고 true인 객체와 false인 객체를

    <>
      <StH1>Working!!🔥🔥🔥</StH1>
      <StList>{working_list}</StList>
      <StH1>Done✔✔✔</StH1>
      <StList>{done_list}</StList>
    </>

 

원하는 곳에 렌더링 해준다.

 

 

토글버튼을 눌러 

isDone이 false인 것은 true로 바꿔주고

true인 것은 false로 바꿔주면

(이 부분은 다음 포스팅에서...)

 

각각 자기한테 맞는 위치에 배치된다.

 

 

 

 

 

 

남은 컴포넌트는

다음 포스팅에서 다루겠다...!

 

 

 

 

 

 

 

 

 

반응형