Storage.get method is not working in useEffect() function

Hi Everyone,

I’m new to Forge development

 const [selectedUsers, setSelectedUsers] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  useEffect(() => {
        // Function to retrieve the field value from Forge Storage
        async function fetchFieldValueFromStorage() {
          try {
          console.log("value retrieved from storage in effect function")  (1)
            const retrievedValue = await storage.get("users-list");
            console.log('Retrieved value:', retrievedValue); (2)
            setSelectedUsers(retrievedValue || []);
            setIsLoading(false);// Set the field value from storage, or an empty string if not found
          } catch (error) {
            console.log('Error fetching field value from Forge Storage:', error);
          }
        }

        fetchFieldValueFromStorage();
      },[]);

Here 1st log works but 2nd log line which is after storage.get method is not working. script is not throwing any error too.

the key used in call is valid one as I could access the same in other functions.

any idea what I’m missing?

Hi Leo

Our documentation on the topic suggest using useEffect(async () => {...

Does this end up working for you?

I’m not an expert on the latest version of React (we’re still stuck with React 16 because of Atlaskit constraints), but I’m pretty sure you’re not supposed to return a Promise in the useEffect hook.

The above code by @Leo follows React documentation examples of using async call in useEffect.

I’d argue that A) this does not solve OPs problem and B) that the Forge documentation is misleading with regard to a subject that is already a hot topic

Thanks @JoshuaHwang @remie , after adding “async” keyword in useEffect function script started working. not sure why it is expecting that while I use that in my inline function already. but new learning though. thanks :slight_smile:

:exploding_head:

From a “let’s follow the React documentation” perspective, would you mind trying the more conventional approach instead of returning Promise to useEffect?

const [selectedUsers, setSelectedUsers] = useState([]);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
      // Function to retrieve the field value from Forge Storage
      const fetchFieldValueFromStorage = async function() {
        try {
          console.log("value retrieved from storage in effect function") ;
          const retrievedValue = await storage.get("users-list");
          console.log('Retrieved value:', retrievedValue);
          return retrievedValue || [];
        } catch (error) {
          console.log('Error fetching field value from Forge Storage:', error);
          return [];
        }
      }

      fetchFieldValueFromStorage().then(setSelectedUsers).finally(() => setIsLoading(false));
    },[]);
1 Like

Also, it seems like storage.get is already an async function, perhaps it’s not even necessary to wrap it in another async function?

const [selectedUsers, setSelectedUsers] = useState([]);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
    storage.get('users-list')
        .then(result => setSelectedUsers(result || [])
        .catch(() => setSelectedUsers([])
        .finally(() => setIsLoading(false));
},[]);

Hi Remie,

Had a chat with the UI kit team. They also agree the disparity between React and @forge/ui is a concern.

UI kit 2 (which is only in preview right now) uses normal React so following React best practice becomes the recommendation there.

1 Like

I know this is a late update, but might be useful for people coming across this thread if they’ve run into similar issues. I’ve written a blog Atlassian Developer Blog: A deeper look at hooks in Forge which explains some of the key differences between useState and useEffect in UI Kit (the original) and React / UI Kit 2 / Custom UI.

3 Likes