TIL|#14 React|TodoList#1の作成
2021年-04-05(月)
TodoTemplate
アプリケーション 見出し 見せてあげる. 子供として. 内部 jsx props 受け取る. レンダー TodoInsert
新しい プロジェクト 入力 および 追加 ≪ステータス|Status|emdw≫ に合格 入力 ≪ステータス|Status|emdw≫ 管理 TodoListItem
プロジェクト内 大寒 情報 見せてあげる. オブジェクトを しちゅう 持ってきてください. ≪ステータス|Status|emdw≫ ついて行く その他 スタイル 見せてあげる. TodoList
n.ハル さぎょう 展開 しちゅう もつ おんど 後. 地図 利用する. 複数 TodoListItem 構成部品 フォーマットコピー
レスポンスモジュールとインストールモジュールの作成
yarn react create-app todoList
node-sass、classname、react-insのインストールyarn add node-sass classnames react-icons
アプリケーション 見出し 見せてあげる. 子供として. 内部 jsx props 受け取る. レンダー
新しい プロジェクト 入力 および 追加 ≪ステータス|Status|emdw≫ に合格 入力 ≪ステータス|Status|emdw≫ 管理
プロジェクト内 大寒 情報 見せてあげる. オブジェクトを しちゅう 持ってきてください. ≪ステータス|Status|emdw≫ ついて行く その他 スタイル 見せてあげる.
n.ハル さぎょう 展開 しちゅう もつ おんど 後. 地図 利用する. 複数 TodoListItem 構成部品 フォーマットコピー
// App.js
import React, { useCallback, useRef, useState } 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,
},
]);
// useRef로 컴포넌트에서 사용할 변수를 만드는 이유는
// id값은 렌더링되는 정보가 아니기 때문이다.
// 즉 화면에 보이지도 않고 이 값이 바뀐다고해서
// 컴포넌트가 다시 렌더링 될 이유가 없기 때문이다.
// 단순히 새로운 항목을 만들때 참조되는 값이다.
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 onDelete = useCallback(
(id) => {
const nextTodos = todos.filter((todo) => todo.id !== id);
setTodos(nextTodos);
},
[todos],
);
const onChecked = useCallback(
(id) => {
const nextTodos = todos.filter((todo) => {
if (todo.id === id) todo.checked = !todo.checked;
return todo;
});
setTodos(nextTodos);
},
[todos],
);
return (
<TodoTemplate>
<TodoInsert onInsert={onInsert} />
{/* TodoList props로 전달 -> TodoList에서 이 값을 받아온 후
TodoListItem으로 변환하여 렌더링 하도록 설정한다.*/}
<TodoList todos={todos} onDelete={onDelete} onChecked={onChecked} />
</TodoTemplate>
);
};
export default App;
TodoTemplate// TodoTemplate.js
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;
// TodoTemplate.scss
.TodoTemplate {
width: 512px;
margin-left: auto;
margin-right: auto;
margin-top: 6rem;
border-radius: 4px;
overflow: hidden;
}
.app-title {
background: #22b8cf;
color: white;
height: 4rem;
font-size: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
}
.content {
background: white;
}
TodoInsert// TodoInsert.js
import React, { useCallback, useState } 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); //현재 useState를 통해 관리하고 있는 value값을 인자로 전달
setValue(''); //value값 초기화
e.preventDefault();
},
[onInsert, value],
);
return (
<form className="TodoInsert" onSubmit={onSubmit}>
<input placeholder="할일 입력" value={value} onChange={onChange} />
<button type="submit">
<MdAdd />
</button>
</form>
);
};
export default TodoInsert;
.TodoInsert {
display: flex;
background: #495057;
input {
// 기본 스타일 초기화
background: none;
outline: none;
border: none;
padding: 0.5rem;
font-size: 1.2rem;
line-height: 1.5;
color: white;
&::placeholder {
color: #dee2e6;
}
// 버튼을 제외한 영역 모두 차지
flex: 1;
}
button {
// 기본 스타일 초기화
background: none;
outline: none;
border: none;
background: #868e96;
color: white;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.5rem;
display: flex;
align-items: center;
cursor: pointer;
transition: 0.1s background ease-in;
&:hover {
background: #adb5db;
}
}
}
TodoList// TodoList.js
import React from 'react';
import TodoListItem from './TodoListItem';
import './TodoList.scss';
const TodoList = ({ todos, onDelete, onChecked }) => {
return (
<div className="TodoList">
{todos.map((todo) => (
<TodoListItem
todo={todo}
key={todo.id}
onDelete={onDelete}
onChecked={onChecked}
/>
))}
</div>
);
};
export default TodoList;
// TodoList.scss
.TodoInsert {
display: flex;
background: #495057;
input {
// 기본 스타일 초기화
background: none;
outline: none;
border: none;
padding: 0.5rem;
font-size: 1.2rem;
line-height: 1.5;
color: white;
&::placeholder {
color: #dee2e6;
}
// 버튼을 제외한 영역 모두 차지
flex: 1;
}
button {
// 기본 스타일 초기화
background: none;
outline: none;
border: none;
background: #868e96;
color: white;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.5rem;
display: flex;
align-items: center;
cursor: pointer;
transition: 0.1s background ease-in;
&:hover {
background: #adb5db;
}
}
}
TodoListItem.jsimport React, { useCallback } from 'react';
import cn from 'classnames';
import './TodoListItem.scss';
import {
MdCheckBoxOutlineBlank,
MdCheckBox,
MdRemoveCircleOutline,
} from 'react-icons/md';
const TodoListItem = ({ todo, onDelete, onChecked }) => {
const { id, text, checked } = todo;
const remove = useCallback(
(e) => {
onDelete(id);
},
[onDelete, id],
);
const check = useCallback(
(e) => {
onChecked(id);
},
[onChecked, checked],
);
return (
<div className="TodoListItem">
<div className={cn('checkbox', { checked })} onClick={check}>
{checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
<div className="text">{text}</div>
</div>
<div className="remove" onClick={remove}>
<MdRemoveCircleOutline />
</div>
</div>
);
};
export default TodoListItem;
// TodoListItem.scss
.TodoListItem {
padding: 1rem;
display: flex;
align-items: center;
&:nth-child(even) {
background: #f8f9fa;
}
}
.checkbox {
cursor: pointer;
flex: 1;
display: flex;
align-items: center;
svg {
font-size: 1.5rem;
}
.text {
margin-left: 0.5rem;
flex: 1;
}
&.checked {
svg {
color: #22b8cf;
}
.text {
color: #adb5bd;
text-decoration: line-through;
}
}
}
.remove {
display: flex;
align-items: center;
font-size: 1.5rem;
color: #ff6b6b;
&:hover {
color: #ff8787;
}
& + & {
border-top: 1px solid #dee2e6;
}
}
Reference
この問題について(TIL|#14 React|TodoList#1の作成), 我々は、より多くの情報をここで見つけました https://velog.io/@goblin820/React-TodoList-만들기-1テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol