반응형
<"리액트를 다루는 기술" 책 참조>
기능 구현하기
1. App에서 todos 상태 사용하기
src > App.js
import React, { 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
}
]);
return (
<TodoTemplate>
<TodoInsert />
<TodoList todos={todos} />
</TodoTemplate>
);
}
export default App;
* props 값 지정하기
src >components > TodoList.js
import React from 'react';
import TodoListItem from './TodoListItem';
import './TodoList.scss';
const TodoList = ({ todos }) => {
return (
<div className="TodoList">
{todos.map(todo => (
<TodoListItem todo={todo} key={todo.id} />
))}
</div>
);
};
export default TodoList;
* props로 받아온 todos 배열을 내장 함수 map을 통해 TodoListItem으로 이루어진 배열로 변환하여 렌더링
(내장 함수 map을 사용하여 key props도 추가로 전달)
src >components > TodoListItem.js
import React from 'react';
import {
MdCheckBoxOutlineBlank,
MdCheckBox,
MdRemoveCircleOutline
} from 'react-icons/md';
import cn from 'classnames';
import './TodoListItem.scss';
const TodoListItem = ({ todo }) => {
const { text, checked } = todo;
return (
<div className="TodoListItem">
<div className={cn('checkbox', { checked })}>
{checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
<div className="text"> { text } </div>
</div>
<div className="remove">
<MdRemoveCircleOutline />
</div>
</div>
);
};
export default TodoListItem;
* 전달 받은 todo를 사용하여 text와 체크 표시를 보여줌.
2. 항목 추가 기능 구현하기
src > App.js
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]
);
return (
<TodoTemplate>
<TodoInsert onInsert={onInsert} />
<TodoList todos={todos} />
</TodoTemplate>
);
}
export default App;
* useRef Hook
- useRef를 사용하여 특정 DOM 선택
* useCallback Hook
- 이벤트 핸들러 함수를 필요할 때만 생성할 수 있음.
- 첫 번쨰 파라미터는 생성하고 싶은 함수, 두 번째 파라미터에는 배열
src >components > 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);
setValue('');
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;
3. 지우기 기능 구현
src > App.js
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]
);
return (
<TodoTemplate>
<TodoInsert onInsert={onInsert} />
<TodoList todos={todos} onRemove={onRemove} />
</TodoTemplate>
);
}
export default App;
src >components > TodoList.js
import React from 'react';
import TodoListItem from './TodoListItem';
import './TodoList.scss';
const TodoList = ({ todos, onRemove }) => {
return (
<div className="TodoList">
{todos.map(todo => (
<TodoListItem todo={todo} key={todo.id} onRemove={onRemove} />
))}
</div>
);
};
export default TodoList;
src >components > TodoListItem.js
import React from 'react';
import {
MdCheckBoxOutlineBlank,
MdCheckBox,
MdRemoveCircleOutline
} from 'react-icons/md';
import cn from 'classnames';
import './TodoListItem.scss';
const TodoListItem = ({ todo, onRemove }) => {
const { id, text, checked } = todo;
return (
<div className="TodoListItem">
<div className={cn('checkbox', { checked })}>
{checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
<div className="text"> { text } </div>
</div>
<div className="remove" onClick={() => onRemove(id)}>
<MdRemoveCircleOutline />
</div>
</div>
);
};
export default TodoListItem;
3. 수정 기능
src > App.js
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;
src >components > TodoList.js
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;
src >components > TodoListItem.js
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={cn('checkbox', { checked })} onClick={() => onToggle(id)}>
{checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
<div className="text"> { text } </div>
</div>
<div className="remove" onClick={() => onRemove(id)}>
<MdRemoveCircleOutline />
</div>
</div>
);
};
export default TodoListItem;
반응형
'JavaScript > React' 카테고리의 다른 글
React Hooks 이란 (0) | 2020.08.17 |
---|---|
React 라이프사이클 메서드 이해하기 (0) | 2020.08.17 |
일정 관리 웹 어플리케이션 만들기 (1) (0) | 2020.08.06 |
Window VS Code 설치(Visual Studio Code) (0) | 2020.08.01 |
React Babel의 transform-class-properties 문법 (0) | 2020.07.29 |