fabiobiondi

Recoil Crud example

Jan 5th, 2021 (edited)
410
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import React, { FormEvent, useEffect, useState } from 'react';
  2. import { atom, selector, useRecoilCallback, useRecoilValue } from 'recoil';
  3.  
  4. /**
  5.  * Description: ASYNC DEMO and useRecoilCallback
  6.  * This demo shows how to do GET, DELETE and POST
  7.  * BONUS: Another use of selectors
  8.  * TODO: fix getUsers dependency in useEffect
  9.  * ASK: best way to handle CRUD operations?
  10.  */
  11. type User = { id: number, name: string, subscribe: boolean };
  12. const MAX_USERS = 12;
  13.  
  14. const currentUsersState = atom<User[]>({
  15.   key: 'users',
  16.   default: []
  17. })
  18.  
  19. const remainingUsers = selector<number>({
  20.   key: 'remainingUsers',
  21.   get: ({ get }) => {
  22.     return MAX_USERS - get(currentUsersState).length
  23.   },
  24. })
  25.  
  26. ///// ROOT COMPO /////
  27. export const Demo6: React.FC = () => {
  28.   const users = useRecoilValue(currentUsersState)
  29.  
  30.   const getUsers =  useRecoilCallback(({set}) => async () => {
  31.     const response =  await fetch('https://jsonplaceholder.typicode.com/users/')
  32.     set(currentUsersState, await response.json());
  33.   }, []);
  34.  
  35.   useEffect(() => {
  36.     getUsers();
  37.   }, [getUsers])
  38.  
  39.   const addUser =  useRecoilCallback(({set}) => async user => {
  40.     const response =  await fetch('https://jsonplaceholder.typicode.com/users',
  41.       {
  42.         method: 'POST', body: JSON.stringify(user),
  43.         headers: { 'Content-Type': 'application/json' },
  44.       })
  45.     set(currentUsersState, [...users, await response.json()]);
  46.   });
  47.  
  48.   const deleteUser =  useRecoilCallback(({set}) => async id => {
  49.     const response =  await fetch('https://jsonplaceholder.typicode.com/users/1', { method: 'DELETE'})
  50.     set(currentUsersState, users.filter((u: User) => u.id !== id));
  51.   });
  52.  
  53.   return (
  54.     <React.Suspense fallback={<div>Loading...</div>}>
  55.       <h1>Demo6</h1>
  56.         <UserForm addUser={addUser}/>
  57.         <UsersListCounter />
  58.         <UsersList users={users} deleteUser={deleteUser} />
  59.     </React.Suspense >
  60.   )
  61. };
  62.  
  63. ////// CHILD COMPONENTS: FORM /////
  64. interface UserFormProps {
  65.   addUser: (payload: Partial<User>) => void;
  66. }
  67. function UserForm(props: UserFormProps) {
  68.   const [value, setValue] = useState<string>('')
  69.   const remainUsers = useRecoilValue(remainingUsers)
  70.  
  71.   function submit(e: FormEvent) {
  72.     e.preventDefault();
  73.     if (remainUsers > 0) {
  74.       props.addUser({ name: value, subscribe: true })
  75.       setValue('')
  76.     }
  77.  
  78.   }
  79.  
  80.   return (
  81.     <form onSubmit={submit}>
  82.       <input type="text" value={value} onChange={e => setValue(e.target.value)} placeholder="Write something and press ENTER" />
  83.     </form>
  84.   )
  85. }
  86.  
  87. ////// CHILD COMPONENTS: LIST /////
  88. interface UserListProps {
  89.   users: User[];
  90.   deleteUser: (id: number) => void;
  91. }
  92.  
  93. function UsersList(props: UserListProps) {
  94.   return <div>
  95.     {
  96.       props.users?.map((u: User, index: number) => {
  97.         return <li key={index} onClick={() => props.deleteUser(u.id)}>{u.name}</li>
  98.       })
  99.     }
  100.   </div>
  101. }
  102.  
  103. ////// CHILD COMPONENTS: LIST COUNTER /////
  104. function UsersListCounter() {
  105.   const users = useRecoilValue(currentUsersState)
  106.   const remainUsers = useRecoilValue(remainingUsers)
  107.  
  108.   return <div>
  109.     Still { remainUsers} of {users.length}
  110.   </div>
  111. }
Add Comment
Please, Sign In to add comment