0

My node.js MySQL query returns a single row wrapped in [RowPacketData] which I can normally access the ID field using results[0].ID.

However, when I store the result in React state (using hooks) it does not work. I can access the result object, but not fields within it.

function MyReactComponent() {
  const [dbEntry, setDbEntry] = useState();

  useEffect(() => {
    const fetchData = async () => {
      const result = await queryFunc(`SELECT * FROM table LIMIT 1`);

      console.log(result[0]); // <-- Works (shows [RowDataPacket] object)
      console.log(result[0].ID); // <-- Works (shows ID)

      setDbEntry(result);
    };

    fetchData();
  }, []);

  console.log(dbEntry[0]); // <-- Works (shows [RowDataPacket] object)
  console.log(dbEntry[0].ID); // <-- TypeError: Cannot read property '0' of undefined

  return (
    <p>
      {dbEntry[0].ID} // <-- How do I render here?
    </p>
  )
}

What's going on here? I have a feeling React is coercing the result object somehow, but I can't figure it out...

1 Answer 1

3

When you need to display data that comes from an async font(API calls for example), it's possible (actually almost certain) that it won't be available by the time the first render occurs, to solve that there is actually a few things you could do:

Placeholder state

You could have a model of what the data will look like described as your initial state, so properties won't be undefined anymore:

const [state, setState] = useState({
    data:[
        {name: ''}
    ]
})

Assuming that your data will have this format accessing state.data[0].name won't throw an error. This could be useful in some cases but I personally don't like the approach.

Conditional Render

At each render you should check for a condition and only if satisfied render the piece of code:

return(
    <>
        <div>Title</div>
        {Boolean(state.data.length) && <div>{state.data[0].name}</div>}
    </>
)

Suspense

That one is brand new, if you have a component tha't need to perform side effects before render it's content, you should have a fallback content to be displayed while the async action is being perform.

<Suspense fallback={<span>Loading</span>}>
    <MYAsyncComponent />
</Suspense>
Sign up to request clarification or add additional context in comments.

2 Comments

Hmm you may be on to something. So then... How do I render those values in my component?
It's called conditional render. I'll update de question

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.