Search code examples
reactjsreact-nativeasync-awaitexpoasyncstorage

React Native AsyncStorage: Get Token and Use it in a refactored API fetch


I have decided to put all my API calls in a seperate file and they are all stateless.

const get = endPoint => {
  let token = "c8c17003468314909737ae7eccd83d4b6eecb792"; //I have put this token here manually    
  return fetch(endPoint, {
    method: "GET",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
      Authorization: "Token " + token
    }
  }).then(response => response.json());
};

and in the same file i have the actual API calls. Example is as follows.

export const loadGroups = () => {
  const endPoint = "https://xxxx.com/api/groups/";
  return get(endPoint);
};

This works perfectly when i call the API from various components as follows.

import { loadGroups } from "../../api";
componentDidMount() {
    loadGroups()
      .then(responseJson => {
        this.setState({
          groups: responseJson
        });
      })
      .catch(error => {
        console.error(error);
      });
      }

However, I want to use AsyncStorage to retrieve a stored token and the due nature of it is to return a promise. This works well when i write the functions of getting the token and storing it in SetState in every component that I do the calls. I really want to refactor the code and using redux is a pain for me.

so far, i have written a file to get the token and it returns a promise.

import { AsyncStorage, Text } from "react-native";

const MyToken = async () => {
  try {
    const retrievedItem = await AsyncStorage.getItem("userToken");
    const item = JSON.parse(retrievedItem);
    return item;
  } catch (error) {
    return null;
  }

};

export default MyToken;

And in the API file, I have re-written the code above to

const get = endPoint => {
  MyToken().then(token => {
    console.log(token, "try 1"); //this works
    const lookupOptions = {
      method: "GET",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        Authorization: "Token " + token
      }
    };
    return fetch(endPoint, lookupOptions).then(response => {
      console.log(response.json(), "promise response,json");
      response.json();
    });
  });

};

However, whenever i call loadGroups().then() (like in the first example) function in any component, I get an errors that loadGroups.then() can't be resolved

Is there any way to resolve this without state, redux, mobx keeping in mind i want my API code in stateless functions in seperate modules.


Solution

  • In V2 of get function, you are not returning any Promise. Either put a return statement in get function like

    const get = endPoint => {
      return MyToken().then(
        ...
      );
    }
    

    Or return Promise explicitly from that function, consider following code snippets

    const get = endPoint => {
      return new Promise((resolve, reject) => {
        MyToken().then(token => {
          ...
          fetch(endPoint, lookupOptions)
          .then(response => response.json())
          .then(resolvedResponse => {
            resolve(resolvedResponse);
          }).catch(error => {
            reject(error);
          });
        });
      });
    };
    

    Hope this will help!