본문 바로가기

Programming/React

Recoil 따라하기 - TodoList

반응형

 

무작정 따라한 소스를 기록으로 남김니다.

 

1. App.js

RecoilRoot 를 사용하여 TodoList 요소를 감싸준다.

import React from 'react';
import TodoList from './components/TodoList'
import { RecoilRoot } from 'recoil';



function App() {
  return (
    <div>
      <RecoilRoot>
        <TodoList />
      </RecoilRoot>
    </div>
  );
}

export default App;

 

2. ./src/recoil/state.js 작성

import { atom } from 'recoil';

export const todoListState = atom({
  key: 'todoListState',
  default: [],
});

3. ./src/components/TodoList.jsx 작성

import React from 'react';
import { useRecoilValue } from 'recoil';

import TodoItemCreator from './TodoItemCreator';
import TodoItem from './TodoItem';
import { todoListState } from '../recoil/state';

const TodoList = () => {
  const todoList = useRecoilValue(todoListState);
  return (
    <div>
      <TodoItemCreator />

      {todoList.map((todoItem) => (
        <TodoItem key={todoItem.id} item={todoItem} />
      ))}
    </div>
  );
};

export default TodoList;

4. ./src/components/TodoItemCreator.jsx 작성

import React, { useState } from 'react';
import { todoListState } from '../recoil/state';
import { useSetRecoilState } from 'recoil';

const TodoItemCreator = () => {
  const [inputValue, setInputValue] = useState('');
  const setTodoList = useSetRecoilState(todoListState);

  const addItem = () => {
    setTodoList((oldTodoList) => {
      const id = oldTodoList.length
      ? oldTodoList[oldTodoList.length - 1].id + 1
      : 0;
      return [
        ...oldTodoList,
        {
          id,
          text: inputValue,
          isComplete: false,
        },
      ];
    });
    setInputValue('');
  };

  const onChange = ({ target: { value } }) => {
    setInputValue(value);
  };

  return (
    <div>
      <input type='text' value={inputValue} onChange={onChange} />
      <button onClick={addItem}>Add</button>
    </div>
  );
};

export default TodoItemCreator;

5. ./src/components/TodoItem.jsx 작성

import React from 'react';
import { useRecoilState } from 'recoil';
import { todoListState } from '../recoil/state';

const TodoItem = ({item}) => {
  const [todoList, setTodoList] = useRecoilState(todoListState);

  const editItemText = ({ target: { value }}) => {
    const newList = todoList.map((listItem) =>
    listItem.id === item.id ? {...listItem, text: value } : listItem
    );
    setTodoList(newList);
  };

  const ToggleItemCompletion = () => {
    const newList = todoList.map((listItem) => 
    listItem.id ===item.id
    ? {...listItem, isComplete: !item.isComplete }
    : listItem
    );
    setTodoList(newList);
  };

  const deleteItem = () => {
    const newList = todoList.filter((listItem) => listItem.id !== item.id);
    setTodoList(newList);
  };
  return (
    <div>
      <input type="text" value={item.text} onChange={editItemText} />
      <input 
        type="checkbox" 
        checked={item.isComplete} 
        onChange={ToggleItemCompletion} 
      />
      <button onClick={deleteItem}>X</button>
    </div>
  );
};

export default TodoItem;

 

6. 결과

yart start

반응형