skip to Main Content

I cannot understand, why do I keep getting "Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead." error.

export async function LobbyPage(props) {
let fetched;
const [data, setState] = useState(null);
axios.get("http://127.0.0.1:8000/api_shop/")
.then(res => {
    fetched = res.data;
    setState(fetched);
})
return ( 
    <>
    <CatNav />
    <main>
        {data.map((current) => (
            <div className="card">
                <img src={current.photo} alt="Nothing"/>
                <div className="card-body">
                    <h5 className="card-title">{current.name}</h5>
                    <p className="card-text">
                        {current.desc}
                    </p>
                    <a href="#" className="btn btn-primary"></a>
                </div>
            </div>
        ))}
    </main>
    </>
)}

It must fetch json data from my DRF backend and just render it via data.map state attribute. Can somebody help with it?

EDIT:
Data is being fetched as well, just something wrong with state and map()

2

Answers


  1. This component isn’t necessarily producing the error. But the component that uses it is. That’s because this component doesn’t return JSX, it returns a Promise:

    export async function LobbyPage(props) {
    

    async functions always return a Promise. The component shouldn’t be async:

    export function LobbyPage(props) {
    

    Aside from that… Don’t make AJAX calls directly in the component’s rendering. That will invoke the AJAX operation every time it renders. And if the operation updates state, that will trigger a re-render and an infinite render loop.

    You can use useEffect with an empty dependency array to invoke the AJAX operation once when the component first loads:

    const [data, setState] = useState(null);
    
    useEffect(() => {
      axios.get("http://127.0.0.1:8000/api_shop/")
      .then(res => {
        setState(fetched);
      });
    }, []);
    

    You also don’t need the fetched variable, it’s not doing anything meaningful.

    Additionally, if you’re mapping over data in the rendering then don’t initialize it to null, since you can’t call .map() on null. Initialize it to an empty array:

    const [data, setState] = useState([]);
    
    Login or Signup to reply.
  2. Since your function is async, the whole function will now return a Promise. All you have to do is to use the await keyword to "wait" for the promise to get resolved, and then return the response. So the modified function would be:

    export async function LobbyPage(props) {
      let fetched;
      const [data, setState] = useState(null);
      const res = await axios.get("http://127.0.0.1:8000/api_shop/");
      fetched = res.data;
      setState(fetched);
      return ( 
        <>
          <CatNav />
          <main>
            {fetched.map((current) => (
              <div className="card">
                <img src={current.photo} alt="Nothing"/>
                <div className="card-body">
                  <h5 className="card-title">{current.name}</h5>
                  <p className="card-text">
                    {current.desc}
                  </p>
                  <a href="#" className="btn btn-primary"></a>
                </div>
              </div>
            ))}
          </main>
        </>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search