recoil 상태를 사용하는 컴포넌트는 부모 트리 어딘가에 나타나는 RecoilRoot가 필요하다. 보통 루트 컴포넌트가 RecoilRoot를 넣기에 적합하다.
// index.js
import { RecoilRoot } from "recoil";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<RecoilRoot>
<App />
</RecoilRoot>
</React.StrictMode>
);
recoil 에서 atom은 상태(state)의 일부를 의미한다. Atoms는 어떤 컴포넌트에서든 읽고 쓸 수 있으며 atom의 값을 읽는 컴포넌트들은 암묵적으로 atom을 구독한다.
그래서 atom에 무슨 변화가 생기면 그 변화가 생긴 atom을 구독하는 컴포넌트들은 리렌더링이 일어난다.
// app.js
import { atom } from "recoil";
import "./App.css";
import TextInput from "./components/TextInput";
import CharacterCount from "./components/CharacterCount";
// 이 atom이 업데이트되면 이 atom을 구독중인 컴포넌트들은 리렌더링이 일어난다.
export const textState = atom({
key: "textState",
default: "",
});
function App() {
return(
<div>
<TextInput />
<CharacterCount />
</div>
)
}
export default App;
컴포넌트가 atom을 읽고 쓰게 하기 위해서는 useRecoilState()를 아래와 같이 사용해야 한다.
// TextInput.js
import React from "react";
import { useRecoilState } from "recoil";
import { textState } from "../App";
const TextInput = () => {
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>
)
};
export default TextInput;
selector는 atom 혹은 다른 selector 상태를 입력받아 동적인 데이터를 반환하는 순수함수다. selector가 참조하던 다른 상태가 변경되면 이도 같이 업데이트되며, 이때 selector를 바라보던 컴포넌트들이 리렌더링 된다.
// index.js
import { atom, selector } from "recoil";
import "./App.css";
import TextInput from "./components/TextInput";
import CharacterCount from "./components/CharacterCount";
export const textState = atom({
key: "textState",
default: "",
});
export const charCountState = selector({
key:'charCountState',
// selector 순수함수인 get
// 사용한 값을 반환하며 매개변수인 콜백 객체 내 get() 메소드로
// 다른 atom 혹은 selector를 참조
get : ({get}) => {
const test = get(textState)
return test.length;
}
})
function App() {
return(
<div>
<TextInput />
<CharacterCount />
</div>
)
}
export default App;
사용할 땐 useRecoilValue()훅을 사용해서 값을 읽을 수 있다.
// CharacterCount.js
import React from 'react'
import { useRecoilValue } from 'recoil'
import { charCountState } from '../App'
const CharacterCount = () => {
const count = useRecoilValue(charCountState)
return (
<div>
Character Count : {count}
</div>
)
}
export default CharacterCount