0

我正在使用 React 开发我的第一个网站,该网站基于 FaunaDB 数据库。我正在使用 Netlify 和 Netlify 函数来访问我的服务器端代码。当尝试使用 react useEffect、useState 和 useRef 从数据库中获取所有数据时,我得到 TypeError: state is undefined。结果在 state 中设置为一个对象数组,所以我的 state 初始值是一个空数组。我尝试转换为类组件,但得到了相同的响应。我想知道我是否不应该使用array.map,但我已经尝试了一个for循环,它不会抛出错误,但它也不会渲染任何东西。

这是我在组件中的代码:

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;

这是我的 getAll 函数:

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

以及它正在获取的功能:

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)
            }
        );
    }
}

这是我第一次使用 React hooks,所以我还在学习中。请帮忙!

4

2 回答 2

2

我认为问题在于您的getAll方法不是异步的,因此await什么都不做。我会让那个函数异步,看看是否能解决你的问题。

此外,useEffect 的第二个参数是一个值数组,useEffect 监视以查看它是否应该再次运行,每次该数组中的一个值更改时,useEffect 挂钩再次运行。由于您正在执行 API 调用,我假设它应该在第一次渲染时运行一次,然后在后续渲染中不再运行。在这种情况下,我会将数组留空,以便它只运行一次。这就是componentDidMount在功能组件中使用钩子复制生命周期方法的方式。我会稍微减少这个钩子,让它看起来更像这样:

useEffect(() => {      
    getAll()
        .then(result => setState(result))
        .catch(e => console.log(e);
    }
}, []);
于 2020-09-28T22:03:47.547 回答
1

我发现我需要做的就是使getAll函数异步,以便await实际执行某些操作,并且我知道它会起作用,因为它fetch是一个承诺。它最终看起来像这样:

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);
    }
}
于 2020-11-03T18:23:10.907 回答