Search code examples
javascriptreactjsreact-nativelocal

In react native, I'm trying to save an object in AsyncStorage, but my app throws an error


I just want to save a simple object into a local storage using AsyncStorage, but my app throws an error saying "[SyntaxError: JSON Parse error: Unexpected identifier "object"]"

Here are my codes:

import forSaving from "./forSaving";

function About() {
  const obj = { id: 1, word: "This is a word" };

  const test = forSaving.store("test", obj);

  const getTest = forSaving.get(test);
  console.log(getTest);
}
export default About;

My goal is just to console.log(getTest) here.

And below, this is a reusable component for AsyncStorage, which I have just copied from a course by Mosh. So, here, nothing should be wrong I guess?

import AsyncStorage from "@react-native-async-storage/async-storage";
import moment from "moment";

const prefix = "cache";
const expiryInMinutes = 10;

const store = async (key, value) => {
  try {
    const item = {
      value,
      timestamp: Date.now(),
    };

    await AsyncStorage.setItem(prefix + key, JSON.stringify(item));
  } catch (error) {
    console.log(error);
  }
};

const isExpired = (item) => {
  //I corrected Data to Date
  const now = moment(Date.now());
  const storedTime = moment(item.timestamp);

  return now.diff(storedTime, "minutes") > expiryInMinutes;
};

const get = async (key) => {
  try {
    //I added await here
    const value = await AsyncStorage.getItem(prefix + key);
    const item = JSON.parse(value);

    if (!item) return null;

    if (isExpired(item)) {
      await AsyncStorage.removeItem(prefix + key);
      return null;
    }

    return item.value;
  } catch (error) {
    console.log(error);
  }
};

export default {
  store,
  get,
};

However, it throws that error... Now I don't know what to do to fix this. Could you please take a look at my codes and tell me where I got it wrong? Thank you in advance.

============================================================

After following the advise and introdusing the sugessted codes, it finally successfully got working!

import forSaving from "./forSaving";

const obj = { id: 1, word: "This is a word" };
const About = () => {
  useEffect(async () => {
    const storeAndGet = async () => {
      forSaving.store("test", obj);

      const getTest = await forSaving.get("test");
      return getTest;
    };

    const result = await storeAndGet();
    console.log(result);
  }, []);
};

export default About;

Oh, this still throws an error saying Warning: useEffect must not return anything besides a function, which is used for clean-up. but I guess this is another story to tackle on


Solution

  • Your question changed while I was typing this up, and it now includes a different error and two versions of your About function. The original answer mostly still applies, but I'll add that if your About function is a React component it needs to return JSX or null, etc.

    Original answer

    I think the error is likely due to the fact that your test variable is a Promise and you should be passing the literal string "test" to the get() call:

    const getTest = forSaving.get("test");
    

    Your store function doesn't (explicitly) return anything, so it's not clear what you're expecting your test variable to be here:

    const test = forSaving.store("test", obj);
    

    The next problem you're going to run into is the fact that get returns a promise, not a value, so you'd need to wait for it to resolve.

    You can solve this using async/await:

    // async is required to use await
    async function About () {
      const obj = { id: 1, word: "This is a word" };
    
      forSaving.store("test", obj);
    
      // wait for the promise returned by get()
      // to resolve to a value before proceeding
      const getTest = await forSaving.get("test");
    }
    

    And finally, you may notice that get() doesn't always resolve to the value you just stored. This is because store() is also asynchronous and if you don't wait for it to finish its work before calling get(), the stored value might not be there yet. Again, the fix is to await store() before proceeding:

    async function About () {
      const obj = { id: 1, word: "This is a word" };
    
      // wait for store to finish before continuing
      await forSaving.store("test", obj);
    
      const getTest = await forSaving.get("test");
    }