다음장 최적화 챕터까지 포함해서 책에 써져있는대로 코드를 짰는데...
이해도 잘 안되고.. 어떻게 정리할지도 모르겠다. 위의 움짤이 그 결과물..
최적화 부분은 스킵해야겠다. 다음에 더 숙련되면 봐야지!
일단은 최적화 부분이랑 scss 부분만 빼고 봐야겠다. 아직 리액트랑 친해지는게 목표니깐..
복습이 필요할듯!
import React , {useState, useRef, useCallback} from 'react';
import TodoTemplate from './components/TodoTemplate';
import TodoInsert from './components/TodoInsert';
import TodoList from './components/TodoList';
const App =() => {
const [todos,setTodos] = useState([
{
id:1,
text:'리액트의 기초 알아보기',
checked:true
},
{
id:2,
text:'컴포넌트 스타일링 해 보기',
checked:true,
},
{
id:3,
text:'일정 관리 앱 만들어 보기',
checked:false,
}
])
const nextId=useRef(4)
const onInsert = useCallback(
text => {
const todo = {
id: nextId.current,
text,
checked:false,
}
setTodos(todos.concat(todo));
nextId.current+=1
},[todos]
)
const onRemove = useCallback(
id => {
setTodos(todos.filter(todo => todo.id !== id))
},[todos]
)
const onToggle = useCallback(
id=>{
setTodos(
todos.map(todo=>
todo.id === id ? {...todo, checked:!todo.checked}:todo)
)
},[todos],
)
return (
<TodoTemplate>
<TodoInsert onInsert={onInsert}/>
<TodoList todos={todos} onRemove={onRemove} onToggle={onToggle}/>
</TodoTemplate>
)
}
export default App;
import React from 'react';
import './TodoTemplate.scss';
const TodoTemplate = ({children}) => {
return (
<div className="TodoTemplate">
<div className="app-title">일정 관리</div>
<div className="content">{children}</div>
</div>
)
}
export default TodoTemplate;
import React , {useState,useCallback} from 'react';
import {MdAdd} from 'react-icons/md';
import './TodoInsert.scss';
const TodoInsert = ({onInsert}) => {
const[value,setValue] = useState('');
const onChange = useCallback(e=>{
setValue(e.target.value)
})
const onSubmit = useCallback(
e=> {
onInsert(value);
setValue('')
e.preventDefault()
},[onInsert,value]
)
return (
<form className="TodoInsert" onSubmit={onSubmit}>
<input
placeholder="할 일을 입력하세요."
onChange={onChange}
value={value}
/>
<button type="submit">
<MdAdd />
</button>
</form>
)
}
export default TodoInsert;
import React from 'react';
import {
MdCheckBoxOutlineBlank,
MdCheckBox,
MdRemoveCircleOutline,
} from 'react-icons/md';
import cn from 'classnames';
import './TodoListItem.scss';
const TodoListItem = ({todo,onRemove,onToggle}) => {
const {id, text, checked} = todo;
return (
<div className="TodoListItem">
<div className="checkbox">
<div className={cn('checkbox',{checked})} onClick={() => onToggle(id)}>
{checked ? <MdCheckBox/> : <MdCheckBoxOutlineBlank/>}
<div className="text">{text}</div>
</div>
</div>
<div className="remove" onClick={() => onRemove(id)}>
<MdRemoveCircleOutline/>
</div>
</div>
)
}
export default TodoListItem;
import React from 'react';
import TodoListItem from './TodoListItem';
import './TodoList.scss';
const TodoList = ({todos,onRemove,onToggle}) => {
return (
<div className="TodoList">
{todos.map( todo => (
<TodoListItem
todo={todo}
key={todo.id}
onRemove={onRemove}
onToggle={onToggle}
/>) ) }
</div>
)
}
export default TodoList;
props로 전달해야 할 함수를 만들 때는 useCallback을 사용하여 함수를 감싸는 걸 습관화하자
import cn from 'classnames'
...(생략)...
<div className={cn('checkbox',{checked})} />
위의 코드의 경우
checked 가 true 일때 className에 'checkbox'가 적용
checked 가 false 일때 className에 아무것도 적용X
쓰기 전에 cmd에서 'yarn add immer' 를 입력해 설치해준다.
이 라이브러리는 불변성을 유지하는 작업을 매우 간단하게 처리할 수 있다.
'불변성에 신경 쓰지 않는 것처럼 코드를 작성하되 불변성 관리는 제대로 해주는 것'이 핵심!
첫 번째 파라미터에는 수정하고 싶은 상태!
두 번째 파라미터에는 상태를 어떻게 업데이트할지 정의하는 함수!
immer 사용 안할시 :
let nextObject = {
...object,
somewhere: {
...object.somewhere,
deep: {
...object.somewhere.deep,
inside:4
}
}
};
(끔ㅡ찍)
immer 사용 할시 :
import produce from 'immer';
const nextState = produce(originalState, draft => {
draft.somewhere.deep.inside = 5;
(편ㅡ안)