1

The code below queries a record from an Atlassian Storage API.

with console.log(data) displays the records as objects objects.

with console.log(data.first_name) and console.log(data.last_name), I can successfully see the name Lucy and Carrots in the console.

Here is my Issue:

When I try to loop through the objects in other to display the records as per code below. it displays Error

TypeError: Cannot read property 'length' of undefined at Object.App

If I remove the projects.length and try to display records, it will show error

TypeError: Cannot read property 'map' of undefined

Below is my effort so far

import api, { route } from "@forge/api";
import ForgeUI, { render, Fragment, Text, IssuePanel, useProductContext, useState, Component, useEffect} from "@forge/ui";

import { storage} from '@forge/api';

 const fetchData = async () => {

//const data = {first_name: 'Lucy', last_name: 'Carrots' };

const data = await storage.get('key1');
console.log(data);
console.log(data.first_name);
console.log(data.last_name);

 };
 
 
const App = () => {
 const [ projects ] = useState(fetchData);
fetchData();

      
  return (
    <Fragment>
     <Text> Display Objects Records</Text>
     
 
         {projects.length ? projects.map((i, v) => (
          <Text key={v}>
            <Text>

<Text>First Name:  {v.first_name}</Text>
<Text>Last Name:  {v.last_name}</Text>
</Text></Text>

        )): <Text>No data stored yet...</Text>}
      

      
  </Fragment>
  );
};

export const run = render(
  <IssuePanel>
    <App />
  </IssuePanel>
);
5
  • what is this const [ projects ] = useState(fetchData); ? It is not the correct way to set the state. And please explain from where you're getting this projects array ? Commented Sep 1, 2021 at 15:57
  • your fetchData function does not update the state Commented Sep 1, 2021 at 15:58
  • Your API call had to be in useEffect(), the initial value of useState Can't be an API call. As the name says, useEffect is for side effects like API calls. Commented Sep 1, 2021 at 16:02
  • The result or record is displayed as an objects not arrays something like {first_name: 'Lucy', last_name: 'Carrots' }; . I can get the First and lastname as I showed in the console.log but my problem is diplaying or rendering the records Commented Sep 1, 2021 at 16:04
  • you cannot use map on an object . Commented Sep 1, 2021 at 16:06

2 Answers 2

1

I see the response data return an object, so you don't need to use array with map.

And you should call API in the useEffect.

  const App = () => {
    const [projects, setProjects] = useState(null);
    
    useEffect(() => {
      const fetchData = async () => {
        const data = await storage.get("key1");
        setProjects(data);
      };
    
      fetchData();
    }, []);
    ...
    {
      projects ? (
        <Text key={v}>
          <Text>
            <Text>First Name: {projects.first_name}</Text>
            <Text>Last Name: {projects.last_name}</Text>
          </Text>
        </Text>
      ) : (
        <Text>No data stored yet...</Text>
      );
    }
    ...
 }
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @Viet for getting back to me. I try to run your code but it displays error showed below Error: Error thrown in the snapshot context. App code snapshot error: Snapshot error occurred: Error: cannot use a hook outsi de of a component Learn more about the snapshot context at http://go.atlassian.com/forge-snapshot- context.
Put all it inside App
please Sir, How can I do that. please can you update your answer between Thanks
0

Try const [projects, setProjects] = useState([]) instead of const [projects] = useState(fetchData). This will make your state start out as an empty array that the API call can exchange for a filled one later by using setProjects().

Then, inside fetchProjects, you can call setProjects(data) to update your state, which will rerender your page.

Finally, calling fetchData() in the place you do now will cause it to be called every time your App is rendered, which is inefficient. Instead, call it inside a useEffect() hook:

useEffect(fetchData, []); 

This will call fetchData() once when the page is loaded.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.