[항해99 4주차] - Redux 개인과제 (2) [코드 뜯어보기]
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로 바꿔주면
(이 부분은 다음 포스팅에서...)
각각 자기한테 맞는 위치에 배치된다.
남은 컴포넌트는
다음 포스팅에서 다루겠다...!