Dette er en workshop som viser grunnleggende bruk av recoil js gjennom å lage en enkel todo app.
Det finnes en tilhørende presentasjon som det kan være greit å se gjennom for å komme i gang med denne workshopen. Ellers er det bare å følge trinnene nedenfor for å komme i gang!
For å komme i gang med workshopen må du ha node og npm installert. Her en noen guides som viser deg hvordan du installerer dette, om du ikke har gjort det alt:
- Installer node og npm på mac
- Installer node og npm på windows
- Installer node og npm på linux (ubuntu)
- Last ned repoet ved å kjøre kommandoen
git clone https://github.com/robertkittilsen/react-recoil-workshopi terminalen. - Naviger til root-folderen ved å kjøre
cd react-recoil-workshop - Start appen ved å kjøre
npm installog deretternpm start. - Åpne koden i din favoritteditor, naviger til
src/Appog følg instruksjonene derifra!
- Recoil dokumentasjon - offisielle nettsiden til Recoil js.
Applikasjonen er skrevet i React og TypeScript med UI komponenter fra Chakra. Åpne App.tsx for å se på applikasjonen.
Her beskriver vi noen scripts som man kan kjøre i terminalen når man er i rotmappen (der man finner ´package.json´ ).
Installerer alle avhengigheter som trengs for å kjøre applikasjonen lokalt.
Starter applikasjonen på adressen http://localhost:3000. Siden vil automatisk bli oppdatert når man gjør en endring i koden.
I denne workshopen skal vi bygge en enkel todo liste app som bruker Recoil js til å håndtere state. Appen vil kunne gjøre følgende:
- Legge til en todo
- Fjerne en todo
- Markere en todo som ferdig
- Filtrere todo items basert på om de er ferdig eller ikke
- Se statistikk om todo listen.
Gjennom å gjøre dette vil vi lære oss om atomer, selektorer og hooks fra Recoil APIet.
Kjør npm start for å se at appen kjører.
Du vil nå se et grunnleggende eksempel på bruk av Recoil. Se gjennom koden for UseRecoilStateExample, Atom Example og Selector Example for å se hvordan disse fungerer.
💡 TodoApp-komponenten som brukes i oppgavene finner du her: src/TodoListApp.tsx. Husk å kommentere inn denne i App.tsx og fjern Examples før du starter på videre oppgaver.
🏆 For at recoil skal fungere må vi legge til RecoilRoot rundt hele appen. Dette gjør vi ved å importere RecoilRoot fra recoil og legge den rundt TodoListApp i App.tsx.
🚨 Løsning
import { RecoilRoot } from "recoil";
<RecoilRoot>
<TodoListApp />
</RecoilRoot>🏆 La oss lage et atom kalt todoListState som vil holde todo-listen vår:
Gå til src/recoil/atoms/todoListAtom.ts og legg til et atom kalt todoListState som har en tom liste som default verdi og "TodoList" som nøkkel.
🚨 Løsning
export const todoListState = atom<TodoItem[]>({
key: 'TodoList',
default: [],
});💡 Flott, du har laget ditt første atom!
Vi gir atomet en unik nøkkel og setter default verdien til et tomt array. For å lese innholdet til dette atomet kan vi bruke useRecoilValue hooken.
🏆 Ta i bruk useRecoilValue med todoListState som parameter i TodoList.tsx. Kall variabelen todoList.
🚨 Løsning
import { useRecoilValue } from "recoil";
import { todoListState } from "../recoil/atoms/todoListAtom";
import TodoItemCreator from "./TodoItemCreator";
import TodoItemView from "./TodoItem";
const TodoList = () => {
// Her leser vi innholdet til todoListState
const todoList = useRecoilValue(todoListState);
return (
<>
<TodoItemCreator />
{todoList.map((todoItem) => (
<TodoItemView item={todoItem} key={todoItem.id} />
))}
</>
);
};💡 For å lage nye todo items trenger vi en setter funksjon som skal oppdatere innholdet i todoListState. Vi kan bruke useSetRecoilState for å få tak i denne funksjonen.
🏆 Lag en setTodoList setter-funksjon ved bruk av denne hooken i TodoItemCreator.tsx. Kommenter inn addItem() og knappen som bruker den i return.
🚨 Løsning
const setTodoList = useSetRecoilState(todoListState);
const addItem = () => {
setTodoList((oldTodoList) => [
...oldTodoList,
{
id: getId(),
text: inputValue,
isComplete: false
}
]);
setInputValue("");
};
return (
<Box my={4}>
<InputGroup>
<Input type="text" value={inputValue} onChange={onChange} />
<Button onClick={addItem} ml={8}>Legg til</Button>
</InputGroup>
</Box>
);💡 Vi bruker useSetRecoilState for å få tak i en setter funksjon som vi kan bruke for å oppdatere todoListState. Vi bruker denne setter funksjonen for å oppdatere todoListState med en ny todo item.
🏆 Ta i bruk useRecoilState for todoListState i stedet for useState i TodoItemView.tsx
🚨 Løsning
const [todoList, setTodoList] = useRecoilState<TodoItem[]>(todoListState);💡 TodoItemView komponenten viser verdien av todo-objektet og den tillater deg å bytte tekst og slette objektet.
💡 Vi bruker useRecoilState til å lese todoListState og til å få en setter-funksjon som vi bruker til å oppdatere todo teksten, markere den som ferdig eller slette den.
💡 For å filtrere todo listen vår kan vi bruke en selector. En selector lar oss definere en funksjon som tar inn ett eller flere atomer som argument og returnerer en verdi.
💡 Filter alternativene våre er: "Show All", "Show Completed" og "Show Uncompleted". Default verdien er "Show All".
🏆 Lag et atom i todoListAtom.ts som heter todoListFilterState med nøkkel "TodoListFilter" og default verdien "Show All".
🚨 Løsning
export const todoListFilterState = atom({
key: 'TodoListFilter',
default: 'Show All',
});💡 Ved å bruke todoListFilterState og todoListState kan vi bygge en filteredTodoListState selector som returnerer en filtrert liste.
🏆 Kommenter inn denne selectoren i todoListSelector.ts:
const filteredTodoListState = selector({
key: 'FilteredTodoList',
get: ({ get }) => {
const filter = get(todoListFilterState);
const list = get(todoListState);
switch (filter) {
case 'Show Completed':
return list.filter((item) => item.isComplete);
case 'Show Uncompleted':
return list.filter((item) => !item.isComplete);
default:
return list;
}
},
});💡 filteredTodoListState følger med på to avhengigheter: todoListFilterState og todoListState. Når en av disse to endrer seg vil filteredTodoListState oppdateres.
🏆 Vis den filtrerte todo listen ved å endre components/TodoList.tsx til å bruke filteredTodoListState i stedet for todoListState.
const todoList = useRecoilValue(filteredTodoListState);Slik det er nå er default verdien "Show all" og det er ikke mulig å endre filteret. Vi kan ta i bruk useRecoilState i TodoListFilters.tsx for å få tak i en setter funksjon som vi kan bruke for å oppdatere todoListFilterState og en getter funksjon slik at vi kan vise nåværende filter.
🏆Implementer useRecoilState for todoListFilterState i TodoListFilters.tsx istedenfor useState og kommenter inn Spacer og TodoListFilters i TodoList.tsx
🚨 Løsning
const [filter, setFilter] = useRecoilState(todoListFilterState);Med bare noen få linjer kode har vi klart å implementere filtrering! Vi vil bruke de samme konseptene for å implementere TodoListStats komponenten.
🏆 Kommenter inn todoListStatsState i todoListSelector.ts:
const todoListStatsState = selector({
key: 'TodoListStats',
get: ({ get }) => {
const todoList = get(todoListState);
const totalNum = todoList.length;
const totalCompletedNum = todoList.filter((item) => item.isComplete).length;
const totalUncompletedNum = totalNum - totalCompletedNum;
const percentCompleted = totalNum === 0 ? 0 : totalCompletedNum / totalNum;
return {
totalNum,
totalCompletedNum,
totalUncompletedNum,
percentCompleted,
};
},
});💡 components/TodoListStatsView komponenten viser antall todo items og antall ferdige todo items.
🏆 Ta i bruk useRecoilValue i TodoListStatsView.tsx for å koble til todoListStatsState selektoren.
Kommenter den inn i TodoList.tsx.
🚨 Løsning
const {
totalNum,
totalCompletedNum,
totalUncompletedNum,
percentCompleted,
} = useRecoilValue(todoListStatsState);Og med det så har vi en fullverdig todo app! 🎉
For å oppsummere; vi har laget en todo liste app som møter alle kravene våre:
- Vi kan legge til todo items
- Vi kan fjerne todo items
- Vi kan markere todo items som ferdig
- Vi kan filtrere todo items basert på om de er ferdig eller ikke
- Vi kan se statistikk over todo listen vår
Håper du har fått et godt inntrykk av hvordan Recoil fungerer og at du har lyst til å bruke det i dine egne prosjekter 🚀