toggle 기능이 있는 todoList 를 구현해보았다.
components 디렉터리에 Todos.js 파일을 생성하고 코드를 구현하였다.
Todos.js 파일에 TodoItem, TodoList, Todos 총 3가지 컴포넌트를 작성했는데, 이렇게 여러개의 컴포넌트를 만드는 이유는 컴포넌트의 리렌더링 성능을 최적화하기 위함이다. 한 파일에 모두 작성을 할 수도 있고, 각각 다른 파일에 분리해도 상관없다.
import React, {useState} from 'react';
const TodoItem = React.memo(function TodoItem({ todo, onToggle }){
return(
<li
style={{textDecoration: todo.done ? 'line-through' : 'none'}}
onClick={()=> onToggle(todo.id)}
>
{todo.text}
</li>
)
})
const TodoList = React.memo(function TodoList({ todos, onToggle }){
return (
<ul>
{todos.map(todo => (
<TodoItem key={todo.id} todo={todo} onToggle={onToggle} />
))}
</ul>
)
});
function Todos({ todos, onCreate, onToggle}){
const [text, setText] = useState('');
const onChange = e => setText(e.target.value);
const onSubmit = e => {
e.preventDefault();
onCreate(text);
setText('');
}
return (
<div>
<form onSubmit={onSubmit}>
<input
value={text}
placeholder="할 일을 입력하세요..."
onChange={onChange}
/>
<button type="submit">ADD</button>
</form>
<TodoList todos={todos} onToggle={onToggle} />
</div>
)
}
export default Todos;
App 에서 렌더링하였다.
import React from 'react';
import CounterContainer from './containers/CounterContainer';
import './App.css';
import TodosContainer from './containers/TodosContainer';
function App() {
return (
<div>
<CounterContainer />
<hr />
<TodosContainer />
</div>
);
}
export default App;
containers 디렉터리에 TodosContainer.js 파일을 생성하고 코드를 구현하였다.
import React, { useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import Todos from '../components/Todos';
import { addTodo, toggleTodo } from '../modules/todos';// 모듈에서 액션 생성함수를 가져온다.
function TodosContainer(){
const todos = useSelector(state => state.todos);
const dispatch = useDispatch();
const onCreate = text => dispatch(addTodo(text));
const onToggle = useCallback(id => dispatch(toggleTodo(id)), [dispatch]);
return <Todos todos={todos} onCreate={onCreate} onToggle={onToggle}/>;
}
export default TodosContainer;
브라우저에 정상적으로 렌더링 되는 것을 볼 수 있다.