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-workshop
i terminalen. - Naviger til root-folderen ved å kjøre
cd react-recoil-workshop
- Start appen ved å kjøre
npm install
og deretternpm start
. - Åpne koden i din favoritteditor, naviger til
src/App
og 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 🚀