gpt4 book ai didi

reactjs - Const 未定义 -> 然而标准解决方案不起作用

转载 作者:行者123 更新时间:2023-12-05 04:34:59 26 4
gpt4 key购买 nike

我想显示一个 mapped list其中“用户名”是来自 Firebase 实时数据库的条目值,对应于每个条目的作者。

以下代码,在 get(UsernameRef).then((snapshot) =>{}) 范围内,按预期返回 undefined reference 错误,'UserName' 被分配了一个值但从未使用过 并且 'UserName' 未定义

  const [RecipeLibrary, setRecipeLibrary] = React.useState([]);
React.useEffect(() => {
const RecipeLibraryRef = ref(db, "Recipes/");
onValue(RecipeLibraryRef, (snapshot) => {
const RecipeLibrary = [];
snapshot.forEach((child) => {
const AuthorUserId = child.key;

child.forEach((grandChild) => {
const UserNameRef = ref(db, "Account/" + AuthorUserId + "/username");
get(UserNameRef).then((snapshot) => {
const UserName = snapshot.val();
});
RecipeLibrary.push({
name: grandChild.key,
author: UserName,
...grandChild.val(),
});
});
});
setRecipeLibrary(RecipeLibrary);
console.log({ RecipeLibrary });
});
}, []);

我试过:

  • 使用 React 状态传递变量 -> 不能在 React useEffect 中使用
  • 导出和导入返回所需用户名的单独函数 -> 返回只能在内部范围内使用
  • 将列表 .push 移动到 Firebase get 范围内 -> React.useState 无法再访问列表

我希望这里有一个简单的解决方案,因为我是新手。您的时间和建议意义重大,谢谢!

更新:

通过将数组 .push 移动到 .then 范围内,我获得了 RecipeLibrary 数组以包含所需的“UserName”条目,并将其命名为 authorHere is a log该数组在设置时(第 59 行)和重新渲染时(第 104 行)。

    child.forEach((grandChild) => {
const UserNameRef = ref(db, "Account/" + AuthorUserId + "/username");
get(UserNameRef).then((snapshot) => {
const UserName = snapshot.val();
RecipeLibrary.push({
name: grandChild.key,
author: UserName,
authorId: AuthorUserId,
...grandChild.val(),
});
});
});
});
setRecipeLibrary(RecipeLibrary);
console.log(RecipeLibrary);

但是,现在映射列表是not rendering at all在屏幕上。

只是添加了一些上下文,对原始代码进行了极小的改动,我一直坚持这一点,以至于我正在考虑在这一点上完全重写以唤起我的内存。哦,这里是呈现映射列表的位,以防万一:

<Box width="75%" maxHeight="82vh" overflow="auto">
{RecipeLibrary.map((RecipeLibrary) => (
<Paper
key={RecipeLibrary.name}
elevation={3}
sx={{

等...

最佳答案

这是一个棘手的问题 - 最简单的选择可能是将 push() setRecipeLibrary() 移动到 然后() 回调,因此它们都在同一范围内,但这会产生一些可怕的副作用(例如,为检索到的每个配方触发重新渲染)。

目标(你已经尽力实现)应该是先等待所有食谱加载完毕,然后使用setRecipeLibrary() 将完整列表设置为状态.假设 get() 返回一个 Promise,一种方法是在异步函数中使用 await:

const [RecipeLibrary, setRecipeLibrary] = React.useState([]);
React.useEffect(() => {
const RecipeLibraryRef = ref(db, "Recipes/");
onValue(RecipeLibraryRef, (snapshot) => {

// An async function can't directly be passed to useEffect(), and
// probably can't be accepted by onValue() without modification,
// so we have to define/call it internally.
const loadRecipes = async () => {
const RecipeLibrary = [];

// We can't use an async function directly in forEach, so
// we instead map() the results into a series of Promises
// and await them all.
await Promise.all(snapshot.docs.map(async (child) => {
const AuthorUserId = child.key;

// Moved out of the grandChild loop, because it never changes for a child
const UserNameRef = ref(db, "Account/" + AuthorUserId + "/username");

// Here's another key part, we await the Promise instead of using .then()
const userNameSnapshot = await get(UserNameRef);
const UserName = userNameSnapshot.val();

child.forEach((grandChild) => {
RecipeLibrary.push({
name: grandChild.key,
author: UserName,
...grandChild.val(),
});
});
}));

setRecipeLibrary(RecipeLibrary);
console.log({ RecipeLibrary });
};

loadRecipes();
});
}, []);

请记住,Promise.all() 在这里不是严格必需的。如果它的使用使它的可读性降低,您可以改为在普通的 for 循环(而不是 forEach)中执行 grandChild 处理,允许您使用 await 而无需映射结果,因为它不会在回调函数中。

如果 snapshot.docs 不可用,但您仍然可以使用 snapshot.forEach(),那么您可以将 Firebase 对象转换为类似于 Convert A Firebase Database Snapshot/Collection To An Array In Javascript 的数组:

// [...]

// Change this line to convert snapshot
// await Promise.all(snapshot.docs.map(async (child) => {
await Promise.all(snapshotToSnapshotArray(snapshot).map(async (child) => {

// [...]

// Define this somewhere visible
function snapshotToSnapshotArray(snapshot) {
var returnArr = [];

snapshot.forEach(function(childSnapshot) {
returnArr.push(childSnapshot);
});

return returnArr;
}

请注意,如果 get() 以某种方式返回 Promise...我担心解决方案会不那么简单。

关于reactjs - Const 未定义 -> 然而标准解决方案不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71134872/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com