Unable to render UI

Hi,

I’m working on fetching some data and then showing it within the UI. However, whenever I add the map() operation a part the code, the entire UI goes blank. I couldn’t get much information using the Forge tunnel as well.

const Text = (props) => (
  <p 
    style={
      {
        'marginBottom': '10px',
      }
    }
  >
    {props.value}
  </p>
)

const CommentSection = (props) => {
  return (
    <Fragment>
      <Text value={JSON.stringify(props.comments)} />
      { /** Problem starts afer adding this */
        props.comments.forEach(
          (comment) => (
            <div key={comment.id}>
              <Text value={comment.body} />
              <Text value={comment.author.displayName} />
            </div>
          )
        )
      }
    </Fragment>
  )
}

function App() {
  const [data, setData] = useState(
    async () =>
      await invoke('getComments').then(data => setData(data))
  );

  return (
    <div>
      {
        data 
        ? (
          <CommentSection comments={data.comments} />
        ) 
        : (
          <Text value="Please wait..." />
        )
      }
    </div>
  )
}

export default App;

Response after invoking getComments()

{
    "comments": [
        {
            "id": "10000",
            "author": {
                "accountId": "5e6c796a84dcfc0cf3919189",
                "displayName": "InspectorGadget",
                "avatarUrl": "https://secure.gravatar.com/avatar/01b6867034633a44a622e6dcd55e2c80?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FI-4.png",
                "timeZone": "Asia/Kuala_Lumpur"
            },
            "body": "<p>Hi</p>",
            "created": "2022-05-11T17:54:42.731+0800",
            "isPublicComment": false
        },
        {
            "id": "10001",
            "author": {
                "accountId": "5e6c796a84dcfc0cf3919189",
                "displayName": "InspectorGadget",
                "avatarUrl": "https://secure.gravatar.com/avatar/01b6867034633a44a622e6dcd55e2c80?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FI-4.png",
                "timeZone": "Asia/Kuala_Lumpur"
            },
            "body": "<p>Public</p>",
            "created": "2022-05-12T23:58:04.577+0800",
            "isPublicComment": true
        }
    ]
}

Please do let me know if I’m making a mistake anywhere else during this process, or any best practices that could be used.

Thanks

Perhaps you meant to use props.comments.map instead of props.comments.forEach?

Hi,

I’ve tried with map() as well before going into forEach. The same behaviour as in the UI wouldn’t render still happened.

You should not use setState within the useState. Use return.

So your code should be:

  const [data, setData] = useState(
    async () =>
      const commentsData = await invoke('getComments');
      return commentsData;
  );

I would also simply store the comments not the whole return object, so I would do this and return empty array if no comments:

  const [data, setData] = useState(
    async () =>
      const commentsData = await invoke('getComments');
      return commentsData ? commentsData.comments : [];
  );

then you can use: data.map(...)

Thanks! I tried the method above and got some weird data error (The invoke command wasn’t actually giving out data - Not sure why, but I can look further into it).

However, I have tried the method below and it works flawlessly - The UI renders with .map() operation too.

  const [data, setData] = useState();

  useEffect(async () => {
    await invoke('getComments').then((data) => {
      setData(data);
    });
  }, []);

Once again - Thank you all for your assistance.