원티드 프리온보딩 세 번째 팀 과제를 받았다 ~~~
리코일은 저번 과제인 영화 검색 앱을 만들 때 사용했지만.. 그때 당시 많이 공부를 못한 상태에서 바로 들어갔기 때문에 원활한 진행을 위해 공부를 해보려고 한다.
화이팅 ~~
참고 : Recoil 공식 문서
이 글은 Recoil 공식 문서를 보고 따라치면서 이해하는 글이라.. 별로입니다. 위의 링크로 가시는 것을 권장드립니다.
RecoilRoot
가 필요하다.RecoilRoot
를 넣기에 가장 좋은 장소이다.<RecoilRoot>
<CharacterCounter />
</RecoilRoot>
const textState = atom({
key: 'textState', // unique ID (다른 atoms/selectors에 관하여)
default: '', // default value (aka initial value)
});
useRecoilState()
를 아래와 같이 사용하면 된다.// CharacterCounter는 상위에서 <RecoilRoot>으로 감싸져있다.
function CharacterCounter() {
return (
<div>
<TextInput />
<CharacterCount />
</div>
);
}
function TextInput() {
// useState와 모양이 같다. 여기는 atom
const [text, setText] = useRecoilState(textState);
const onChange = (event) => {
setText(event.target.value);
};
return (
<div>
<input type="text" value={text} onChange={onChange} />
<br />
Echo: {text}
</div>
);
}
Atoms는 애플리케이션 상태의 source of truth를 갖는다.
todo 리스트에서 source of truth는 todo 아이템을 나타내는 객체로 이루어진 배열이 될 것이다.
atom 리스트를 todoListState
라고 하고 이것을 atom()
를 이용해서 생성한다.
const todoListState = atom({
key : 'todoListState',
default : [],
})
useRecoilValue()
훅을 컴포넌트에서 사용할 수 있다.function TodoList() {
const todoList = useRecoilValue(todoListState);
return (
<>
<TodoItemCreator />
{todoList.map((todoItem) => (
<TodoItem key={todoItem.id}
)
</>
)
}
todoListState
내용을 업데이트하는 setter 함수에 접근해야 한다.todoItemCreator
컴포넌트의 setter 함수를 얻기 위해 useSetRecoilState()
훅을 사용할 수 있다.function TodoItemCreator() {
const [inputValue, setInputValue] = useState('');
// 새로운 todoList를 set해주는 부분
const setTodoList = useSetRecoilState(todoListState);
const addItem = () => {
// 이전 todoList 데이터와 새로운 데이터를 합한 데이터가 todoListState로 업데이트 된다.
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>
);
}
// 고유한 Id 생성을 위한 유틸리티
let id = 0;
function getId() {
return id++;
}
TodoItem
컴포넌트는 todo 리스트의 값을 표시하는 동시에 텍스트를 변경하고 항목을 삭제할 수 있다.todoListState
를 읽고 항목 텍스트를 업데이트하고, 완료된 것으로 표시하고, 삭제하는 데 사용하는 setter 함수를 얻기 위해 useRecoilState()
를 사용한다.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,
});
// newList는 수정한 todo
// 아래에서 업데이트 해준다.
setTodoList(newList);
};
// todo가 완료되었는지 확ㅇ니하는 부분
const toggleItemCompletion = () => {
const newList = replaceItemAtIndex(todoList, index, {
...item,
isComplete: !item.isComplete,
});
// 수정한 todo를 업데이트
setTodoList(newList);
};
const deleteItem = () => {
// todo 삭제
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)];
}