メインコンテンツにスキップ

Atoms

Atomsには、アプリケーションの状態に関する真実が含まれています。当社のTodoリストでは、真実のソースはオブジェクトの配列であり、各オブジェクトはTodoアイテムを表します。

リストアトムにtodoListStateという名前を付け、atom()関数を使用して作成します

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

アトムには一意のキーが与えられ、既定値は空の配列に設定されます。このアトムの内容を読み取るには、TodoListコンポーネントでuseRecoilValue()フックを使用できます

function TodoList() {
const todoList = useRecoilValue(todoListState);

return (
<>
{/* <TodoListStats /> */}
{/* <TodoListFilters /> */}
<TodoItemCreator />

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

コメントアウトされたコンポーネントは、以降のセクションで実装されます。

新しいTodoアイテムを作成するには、todoListStateの内容を更新するセッター関数にアクセスする必要があります。useSetRecoilState() フックを使用して、TodoItemCreatorコンポーネントでセッター関数を取得できます

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

const addItem = () => {
setTodoList((oldTodoList) => [
...oldTodoList,
{
id: getId(),
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>
);
}

// utility for creating unique Id
let id = 0;
function getId() {
return id++;
}

セッター関数の更新プログラムフォームを使用して、古いTodoリストに基づいて新しいTodoリストを作成することに注意してください。

TodoItemコンポーネントは、Todoアイテムの値を表示すると同時に、テキストを変更してアイテムを削除することもできます。 useRecoilState()を使用してtodoListStateを読み取り、アイテムのテキストを更新したり、完了と削除のマークを付けたり、削除したりするために使用するセッター関数を取得します

function TodoItem({item}) {
const [todoList, setTodoList] = useRecoilState(todoListState);
const index = todoList.findIndex((listItem) => listItem === item);

const editItemText = ({target: {value}}) => {
const newList = replaceItemAtIndex(todoList, index, {
...item,
text: value,
});

setTodoList(newList);
};

const toggleItemCompletion = () => {
const newList = replaceItemAtIndex(todoList, index, {
...item,
isComplete: !item.isComplete,
});

setTodoList(newList);
};

const deleteItem = () => {
const newList = removeItemAtIndex(todoList, index);

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>
);
}

function replaceItemAtIndex(arr, index, newValue) {
return [...arr.slice(0, index), newValue, ...arr.slice(index + 1)];
}

function removeItemAtIndex(arr, index) {
return [...arr.slice(0, index), ...arr.slice(index + 1)];
}

これで、完全に機能するTodoリストが完成しました! 次のセクションでは、セレクターを使用してリストを次のレベルに引き上げる方法について説明します。