Why is my functional react component's state throwing TypeError: state is undefined?
Why is my functional react component's state throwing TypeError: state is undefined?
我正在使用 React 创建我的第一个网站,该网站基于 FaunaDB 数据库。我正在使用 Netlify 和 Netlify 函数来访问我的服务器端代码。当尝试使用 react useEffect、useState 和 useRef 从数据库中获取所有数据时,我得到 TypeError: state is undefined。结果在 state 中设置为一个对象数组,所以我的 state 初始值是一个空数组。我尝试转换为 class 组件,但我得到了相同的响应。我想知道我是否不应该使用 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,所以我还在学习中。请帮忙!
我认为问题在于您的 getAll
方法不是异步的,因此 await
不执行任何操作。我会让该函数异步,看看是否能解决您的问题。
此外,useEffect 的第二个参数是一个值数组,useEffect 会监视它是否应该再次 运行,每当该数组中的一个值更改 useEffect 挂钩时 运行s再次。由于您正在进行 API 调用,我假设它应该在第一次渲染时 运行 一次,然后在后续渲染中不会再一次。在那种情况下,我会将数组留空,这样它就只有 运行s 一次。这就是 componentDidMount
生命周期方法是如何在功能组件中使用钩子复制的。我会稍微减少这个钩子看起来更像这样:
useEffect(() => {
getAll()
.then(result => setState(result))
.catch(e => console.log(e);
}
}, []);
我发现我需要做的就是让 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);
}
}
我正在使用 React 创建我的第一个网站,该网站基于 FaunaDB 数据库。我正在使用 Netlify 和 Netlify 函数来访问我的服务器端代码。当尝试使用 react useEffect、useState 和 useRef 从数据库中获取所有数据时,我得到 TypeError: state is undefined。结果在 state 中设置为一个对象数组,所以我的 state 初始值是一个空数组。我尝试转换为 class 组件,但我得到了相同的响应。我想知道我是否不应该使用 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,所以我还在学习中。请帮忙!
我认为问题在于您的 getAll
方法不是异步的,因此 await
不执行任何操作。我会让该函数异步,看看是否能解决您的问题。
此外,useEffect 的第二个参数是一个值数组,useEffect 会监视它是否应该再次 运行,每当该数组中的一个值更改 useEffect 挂钩时 运行s再次。由于您正在进行 API 调用,我假设它应该在第一次渲染时 运行 一次,然后在后续渲染中不会再一次。在那种情况下,我会将数组留空,这样它就只有 运行s 一次。这就是 componentDidMount
生命周期方法是如何在功能组件中使用钩子复制的。我会稍微减少这个钩子看起来更像这样:
useEffect(() => {
getAll()
.then(result => setState(result))
.catch(e => console.log(e);
}
}, []);
我发现我需要做的就是让 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);
}
}