Search code examples
javascriptreactjsreact-hooksfaunadbnetlify-function

Why is my functional react component's state throwing TypeError: state is undefined?


I'm working on my first website in React, which is based off of a FaunaDB database. I'm using Netlify and Netlify functions to access my server-side code. When trying to to get all of the data from the database using react useEffect, useState, and useRef, I get TypeError: state is undefined. The results are set in state as an array of objects, so my initial value of state is an empty array. I tried converting to a class component, but I get the same response. I'm wondering if I shouldn't use array.map, but I already tried a for loop, and it doesn't throw an error but it also doesn't render anything.

Here is my code in the Component:

import React, { useState, useEffect, useRef } from "react";
import { getAll } from "../../fauna";

const AllResults = () => {
    const [state, setState] = useState([]);
    const isRendered = useRef(false);

    useEffect(() => {
        const getResults = async () => {
            try {
                if (!isRendered.current) {
                    const result = await getAll();
                    setState(result);
                    isRendered.current = true;
                }
            } catch (e) {
                console.log(e);
            }
        }

        getResults();
    }, [isRendered, setState]);

    console.log(state);

    const allResults = state.map((l) => {
        return <p key={ l.key } { ...l }></p>
    });
    
    return allResults;
}

export default AllResults;

Here is my getAll function:

export const getAll = () => {
    return fetch(
        "/.netlify/functions/read-all"
    )
    .then(
        (response) => {
            return response.json();
        }
    )
    .catch(
        (error) => {
            console.error(error);
        }
    );
}

and the function it is fetching:

const faunadb = require("faunadb");
const dotenv = require("dotenv");
const path = require("path");

dotenv.config({ path: path.resolve("../../../.env") });
const q = faunadb.query;
const db = new faunadb.Client({ secret: process.env.FAUNA_SERVER_KEY });

exports.handler = async (_event, _context, callback) => {
    console.log("Reading database...");
    try {
        const res = await db.query(
            q.Paginate(
                q.Match(
                    q.Index("all")
                )
            )
        );
        const all = res.data;
        console.log("Success! ${all.length} items found");

        const getAll = all.map(
            (ref) => {
                return q.Get(ref);
            }
        );
        const ret = await db.query(getAll);
        return callback(
            null,
            {
                statusCode: 200,
                body: JSON.stringify(ret.map((refs) => refs.data))
            }
        );
    }
    catch (err) {
        console.log("Error: ", err);
        return callback(
            null,
            {
                statusCode: 400,
                body: JSON.stringify(err)
            }
        );
    }
}

This is my first time using React hooks, so I'm still learning. Please help!


Solution

  • I figured out that all I needed to do was to make the getAll function asynchronous, so that the await would actually do something, and I knew it would work because fetch is a promise. It ended up looking like this:

    export const getAll = async () => {
        try {
          const response = await fetch(
            "/.netlify/functions/read-all"
          )
          
          const json = response.json();
    
          console.log(json);
          return json;
        } catch (error) {
          console.error(error);
        }
    }