[Recoil이란?]
https://recoiljs.org/ko/docs/introduction/motivation
보통 리액트에서는 전역 상태 관리로 리덕스를 많이 사용했다.
recoil은 리덕스와 마찬가지로 전역으로 데이터를 구독해서 컴포넌트에서 사용할 수 있는데 훨씬 간단한 라이브러리이다.
[사용법]
recoil/todo.ts 파일을 만든다.
import { atom } from "recoil";
export interface ITodoTypes {
id: number;
contents: string;
isCompleted: boolean;
}
export const inputState = atom<string>({
key: "inputState",
default: "",
});
export const todoState = atom<ITodoTypes[]>({
key: "todos",
default: [
{
id: 1,
contents: "스트레칭 하기",
isCompleted: false,
},
],
});
이렇게 atom으로 지정하면 전역적으로 이 todoState와, inputState에 접근할 수 있게 된다.
key는 고유한 값이다. 다른 atom과 중복되면 안된다.
todo list를 생성하고 삭제하고 완료 표시를 하려면
전역에 있는 데이터의 배열에 접근해서 수정할 수 있어야한다.
이것은 컴포넌트에서 리액트 훅 처럼 간편하게 사용할 수 있는데
두가지 방법이 있다.
1번
const [todos, setTodos] = useRecoilState<ITodoTypes[]>(todoState);
useRecoilState를 사용하여 마치 useState처럼 사용하는 방법
todos의 initialState는 atom으로 생성한 todoState이고,
setTodos를 사용하면 전역 데이터가 변경된다.
2번
const todos = useRecoilValue<ITodoTypes[]>(todoState);
const setTodo = useSetRecoilState<ITodoTypes[]>(todoState);
todos와 setter을 따로 쓰는 법
useRecoilValue를 사용해서 atom으로 만든 todoState를 가져오고,
useSetRecoilState를 사용해서 set을 한다(데이터 변경)
[추가하기]
//pages/RecoilPrc.tsx
import React, {
ChangeEvent,
KeyboardEventHandler,
useCallback,
useState,
} from "react";
import {
useRecoilState,
selector,
useSetRecoilState,
useRecoilValue,
} from "recoil";
import TodoItem from "../components/TodoItem";
import { numberLabelState, numberState } from "../state/state";
import { Input, Button } from "@mui/material";
import { inputState, ITodoTypes, todoState } from "../recoil/todo";
const RecoilPrc = (): JSX.Element => {
const [content, setContent] = useRecoilState<string>(inputState);
const todos = useRecoilValue<ITodoTypes[]>(todoState);
const setTodo = useSetRecoilState<ITodoTypes[]>(todoState);
//todo 추가하기
const addTodo = useCallback((): void => {
if (!content.trim()) {
// 빈칸 입력 방지
return;
}
const nextId = todos.length > 0 ? todos[todos.length - 1].id + 1 : 0;
const todo: ITodoTypes = {
id: nextId,
contents: content,
isCompleted: false,
};
setTodo([...todos, todo]);
setContent("");
}, [content, setContent, setTodo, todos]);
//todo input text
const onChange = useCallback(
(e: ChangeEvent<HTMLInputElement>): void => {
setContent(e.target.value);
},
[setContent]
);
//todo add keybord event
const onKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLInputElement>): void => {
if (e.key === "Enter") {
addTodo();
}
},
[addTodo]
);
return (
<div>
<h2>This is recoil</h2>
<div>
<Input
type="text"
placeholder="todo입력"
value={content}
onChange={onChange}
onKeyDown={onKeyDown}
/>
<Button variant="contained" onClick={addTodo}>
등록하기
</Button>
</div>
{todos.map((todo: ITodoTypes) => {
const { id, contents, isCompleted } = todo;
return (
<TodoItem
key={id}
id={id}
content={contents}
isCompleted={isCompleted}
/>
);
})}
</div>
);
};
export default RecoilPrc;
여기서는 2번 방법을 사용한다.
addTodo메소드를 보면 useState처럼 사용하면 되는 것을 알 수 있다.
[완료상태 업데이트, 삭제하기]
import { Button } from "@mui/material";
import React, { useCallback } from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { ITodoTypes, todoState } from "../recoil/todo";
interface PropTypes {
id: number;
content: string;
isCompleted: boolean;
}
const TodoItem = (props: PropTypes) => {
const { id, content, isCompleted } = props;
const [todos, setTodos] = useRecoilState<ITodoTypes[]>(todoState);
const handleComplete = useCallback(
(id: number) => {
setTodos(
todos.map((todo: ITodoTypes) => {
return todo.id === id
? {
...todo,
isCompleted: !todo.isCompleted,
}
: todo;
})
);
},
[setTodos, todos]
);
const deleteTodo = useCallback(
(id: number) => {
setTodos(todos.filter((todo: ITodoTypes) => todo.id !== id));
},
[setTodos, todos]
);
return (
<div style={{ display: "flex" }}>
<h2
onClick={() => {
handleComplete(id);
}}
>
{id}. {content} {isCompleted ? "o" : "x"}
</h2>
<Button variant="contained" onClick={() => deleteTodo(id)}>
삭제
</Button>
</div>
);
};
export default TodoItem;
여기서는 1번방법으로 사용한다.
마찬가지로 setTodo함수에 파라미터로 todoState에 들어갈 값을 넣으면 된다.
[결과]
'WEB > REACT' 카테고리의 다른 글
[REACT] slot machine 만들기 (0) | 2021.12.28 |
---|---|
[REACT] ag grid를 사용하여 테이블 만들기/ editable, row selection, cell renderer (0) | 2021.12.28 |
[REACT] react-table row selection/ column hidding (0) | 2021.12.17 |
[REACT] redux에 typescript적용하기 (0) | 2021.12.17 |
[REACT] mui data grid로 리액트 테이블 만들기 (0) | 2021.12.16 |