import React from "react";
import styled, { css } from "styled-components";
import { MdDone, MdDelete } from "react-icons/md";
const Remove = styled.div`
display: flex;
align-items: center;
justify-content: center;
color: #dee2e6;
font-size: 24px;
cursor: pointer;
&:hover {
color: #ff6b6b;
}
display: none;
`;
const TodoItemBlock = styled.div`
display: flex;
align-items: center;
padding-top: 12px;
padding-bottom: 12px;
&:hover {
${Remove} {
display: initial;
}
}
`;
const CheckCircle = styled.div`
width: 32px;
height: 32px;
border-radius: 16px;
border: 1px solid #ced4da;
font-size: 24px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20px;
cursor: pointer;
${(props) =>
props.done &&
css`
border: 1px solid #38d9a9;
color: #38d9a9;
`}
`;
const Text = styled.div`
flex: 1;
font-size: 21px;
color: #495057;
${(props) =>
props.done &&
css`
color: #ced4da;
`}
`;
function TodoItem({ id, done, text, onRemove, onToggle }) {
return (
<TodoItemBlock>
<CheckCircle done={done} onClick={() => onToggle(id)}>
{done && <MdDone />}
</CheckCircle>
<Text done={done}>{text}</Text>
<Remove onClick={() => onRemove(id)}>
<MdDelete />
</Remove>
</TodoItemBlock>
);
}
export default React.memo(TodoItem);
함수형 업데이트란? setTodos를 사용할 때, 새로운 상태를 파라미터로 넣는 대신에 상태 업데이트를 어떻게 할지 정의해 주는 업데이트 함수 넣는 것
const [number, setNumber]= useState(0);
const onIncrease = useCallback(
()=>setNumber(prev=>prev+1);,
[],
);
import { createGlobalStyle } from "styled-components";
import React, { useCallback, useRef, useState } from "react";
import TodoTemplate from "./TodoTemplate";
import TodoHead from "./TodoHead";
import TodoList from "./TodoList";
import TodoCreate from "./TodoCreate";
const GlobalStyle = createGlobalStyle`
body {
background: #74992e;
}
`;
const App = () => {
const [todos, setTodos] = useState([
{
id: 1,
text: "todo 1",
done: true
},
{
id: 2,
text: "todo 2",
done: true
},
{
id: 3,
text: "todo 3",
done: false
}
]);
const nextId = useRef(4);
const onInsert = useCallback((text) => {
const todo = {
id: nextId.current,
text,
done: false
};
setTodos((todos) => todos.concat(todo));
nextId.current += 1;
}, []);
const onRemove = useCallback((id) => {
setTodos((todos) => todos.filter((todo) => todo.id !== id));
}, []);
const onToggle = useCallback((id) => {
setTodos((todos) =>
todos.map((todo) =>
todo.id === id ? { ...todo, done: !todo.done } : todo
)
);
}, []);
return (
<>
<GlobalStyle />
<TodoTemplate>
<TodoHead />
<TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
<TodoCreate onInsert={onInsert} />
</TodoTemplate>
</>
);
};
export default App;
import { createGlobalStyle } from "styled-components";
import React, { useCallback, useReducer, useRef, useState } from "react";
import TodoTemplate from "./TodoTemplate";
import TodoHead from "./TodoHead";
import TodoList from "./TodoList";
import TodoCreate from "./TodoCreate";
function createBulkTodos() {
const array = [
{
id: 1,
text: "todo 1",
done: true
},
{
id: 2,
text: "todo 2",
done: true
},
{
id: 3,
text: "todo 3",
done: false
}
]
return array;
}
const GlobalStyle = createGlobalStyle`
body {
background: #74992e;
}
`;
const reducer = (todos, action) => {
switch (action.type) {
case "INSERT":
return todos.concat(action.todo);
case "REMOVE":
return todos.filter((todo) => todo.id !== action.id);
case "TOGGLE":
return todos.map((todo) =>
todo.id === action.id ? { ...todo, checked: !todo.checked } : todo
);
default:
return todos;
}
};
const App = () => {
const [todos, dispatch] = useReducer(reducer, undefined, createBulkTodos);
const nextId = useRef(4);
const onInsert = useCallback((text) => {
const todo = {
id: nextId.current,
text,
done: false
};
dispatch({ type: "INSERT", todo });
nextId.current += 1;
}, []);
const onRemove = useCallback((id) => {
dispatch({ type: "REMOVE", id });
}, []);
const onToggle = useCallback((id) => {
dispatch({ type: "TOGGLE", id });
}, []);
return (
<>
<GlobalStyle />
<TodoTemplate>
<TodoHead />
<TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
<TodoCreate onInsert={onInsert} />
</TodoTemplate>
</>
);
};
export default App;