【发布时间】:2022-01-05 05:31:46
【问题描述】:
这是一个 next.js 站点,因为我的导航栏组件和我的购物车页面都应该可以访问我的购物车内容,所以我为它们创建了一个上下文。如果我尝试渲染页面,我会得到:
未处理的运行时错误
TypeError: Cannot read properties of undefined (reading 'key')
obs:cartContent 数组存在且长度为 1,我可以通过使用 setTimeout 延迟渲染数据的时间来获取它,但是在获取后无法立即渲染它。
我需要在返回 firebase 的数据后渲染它,但总是遇到提到的错误。
这是我的 _app.tsx 文件
function MyApp({ Component, pageProps }) {
// set user for context
const userContext = startContext();
return (
<UserContext.Provider value = { userContext }>
<Navbar />
<Component {...pageProps} />
<Toaster />
</UserContext.Provider>
);
}
export default MyApp
这个文件有 startContext 函数,它返回上下文,所以它可以被使用。
export const startContext = () => {
const [user] = useAuthState(auth);
const [cart, setCart] = useState(null);
const [cartContent, setCartContent] = useState(null);
useEffect(() => {
if (!user) {
setCart(null);
setCartContent(null);
}
else {
getCart(user, setCart, setCartContent);
}
}, [user]);
return { user, cart, setCart, cartContent, setCartContent };
}
此文件包含 getCart 函数。
export const getCart = async (user, setCart, setCartContent) => {
if (user) {
try {
let new_cart = await (await getDoc(doc(firestore, 'carts', user.uid))).data();
if (new_cart) {
let new_cartContent = []
await Object.keys(new_cart).map(async (key) => {
new_cartContent.push({...(await getDoc(doc(firestore, 'products-cart', key))).data(), key: key});
});
console.log(new_cartContent);
setCartContent(new_cartContent);
console.log(new_cartContent);
setCart(new_cart);
}
else {
setCart(null);
setCartContent(null);
}
} catch (err) {
console.error(err);
}
}
}
这是 cart.tsx 网页。当我加载它时,我得到了提到的错误。
export default () => {
const { user, cart, cartContent } = useContext(UserContext);
return (
<AuthCheck>
<div className="grid grid-cols-1 gap-4">
{cartContent && cartContent[0].key}
</div>
</AuthCheck>
)
}
我尝试以多种不同的方式呈现购物车的 content[0].key,但都做不到。总是得到错误,好像它是未定义的。做一个 setTimeout hack 是可行的,但是,我真的很想以一种体面的方式解决这个问题,所以它至少在不依赖于 firebase 的响应时间/互联网延迟的意义上是防错的。
编辑: 由于它与 setTimeout 一起使用,因此感觉就像一个竞争条件,如果使用 setCartContent,它会触发重新渲染,但 setCartContent 无法在渲染内容之前完成,因此它会将状态 cartContent 视为未定义,以后不会再次触发。
【问题讨论】:
-
你能把你的代码放在一个沙箱里吗?因为我看上面的代码没有看到任何错误。我觉得很好。
标签: reactjs typescript next.js react-context