Recoil: set async API response to atom

Created on 18 Jun 2020  路  6Comments  路  Source: facebookexperimental/Recoil

I'm new to Recoil. I have an API that gives me user details, something like this

{
"name": userName,
"age" : 28,
"degree": MS,
"address": ...
}

I have a selector that gives me the API response. I would like to store each of these values to a recoil state/atom. So that I can use it across the application. We can't use an atom setter inside a selector. After getting the selector response from import, I was not able to set in the react component also. as it goes to the infinite loop. Please guide me.

export const userdetails = selector({
    key: 'userdetails',
    get: async ({ get }) => {
        try {
            const response = await axios.get('/user'));
            const data = await response.data;
            return data;
        } catch (error) {
            throw error;
        }
    }
});

All 6 comments

this is my simple way to perfom that:

  1. create an atom to handle search
export const handleUserSearch  = atom({
key:'handleUserSearch',
default: false
})
; 2. **create a selector wich handle that atom**

export const userDetails = selector({
key:'userDetails',
get : async ({ get }) => {
   try{
           const handleUserSearch = get(handleUserSearch);
           let response;

           if(handleUserSearch){
             response = await axios.get('/user'));
             return response.data;
            }
      return response;
   }catch(error){
     throw error;
    }
})
  1. some where in your component to search

//imports
import * as React from 'react';
import { useRecoilValue, useRecoilState } from 'recoil';
import {handleUserSearch, userDetails } from '../store';

//init variable for handle results and perfom search
const [handleUserSearch , sethandleUserSearch] = useRecoilState(handleUserSearch);
const userDetails = useRecoilValue(userDetails);

//use react hooks useEffet to handle changes
React.useEffet(()=>{
//check if userDeatails has data
if(userDetails !== undefined){
//there's data
//after getting data we stop searching
sethandleUserSearch(false);
}else{
//there's no data
}
},[sethandleUserSearch, userDetails]);

const handleSearch = () => {
   //search data
   sethandleUserSearch(true);
}
return (
<>
<button onClick={handleSearch} disable={handleUserSearch}>Search user</button>
</>
)

4.in other component


//imports
import * as React from 'react';
import { useRecoilValue} from 'recoil';
import {userDetails } from '../store';

//init variable for handle results
const userDetails = useRecoilValue(userDetails);

return (
<>
{userDetails &&
<p>{userDetails.name}</p>
}</>

)

i just test it and it work perfectly

Thanks @dommi10 it helps.
In my case, I also need a setter. which will update the user details (say which takes field 'name' and value 'userName2' as input and updates the recoilState. How can I write set in Selector? or should I have a SelectorFamily for it?

Yes i think. let's update the code below:

1. let's update own selector


export const userDetails = selector({
    key:'userDetails',
    get : async ({ get }) => {
        try{
               const handleUserSearch = get(handleUserSearch);
               let response;

               if(handleUserSearch){
                 response = await axios.get('/user'));
                 return response.data;
                }
          return response;
       }catch(error){
         throw error;
        }
    },
    set: async( { set }, newValue)=>{
    //update to server
         try{
             await axios.post('/updateUser',{newValue}));
          }catch(error){
             throw error;
          }
    //update local state
        set(
           handleUserSearch,
           true
        );
    }});

2. to update component value


//imports
import * as React from 'react';
import { useRecoilState } from 'recoil';
import { userDetails } from './store';

//use recoil state to update user
const [ userDetails, setUserDetails ]   = useRecoilState(userDetails);

//create local use state with hooks
const [name, setName ] = React.useState("");

//update function
const updateDetail = () => {
setUserDetails({...userDetails, name});
}

//handle change
const handleNameChange = (e, {value}) =>setName(value);

return(
<>
<input onChange={handleNameChange } placeholder='name'/>
<button onClick={updateDetail}>update</button>
</>
)

i think this can work.
for more info follow this link

Thanks @dommi10 this helps.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ymolists picture ymolists  路  3Comments

yuantongkang picture yuantongkang  路  3Comments

adrianbw picture adrianbw  路  3Comments

jamiebuilds picture jamiebuilds  路  3Comments

art1373 picture art1373  路  4Comments