Javascript 道具准备就绪之前的子组件渲染
我相当肯定我知道这个问题。我认为这是因为在道具准备好之前子组件渲染。在看了很多教程和文档之后,我就是不知道我做错了什么 当页面打开时,我使用钩子和useEffect从firestore获取数据。之后,我想将数据传递给子组件“Table.js”以显示。 如果父组件中有该表,则它可以正常工作,但当我将该表移动到其自己的组件时,会出现一个错误,即forms.map不是函数`TypeError:forms.map不是函数 下面是我的父组件代码MainScreen.jsJavascript 道具准备就绪之前的子组件渲染,javascript,reactjs,async-await,react-hooks,use-effect,Javascript,Reactjs,Async Await,React Hooks,Use Effect,我相当肯定我知道这个问题。我认为这是因为在道具准备好之前子组件渲染。在看了很多教程和文档之后,我就是不知道我做错了什么 当页面打开时,我使用钩子和useEffect从firestore获取数据。之后,我想将数据传递给子组件“Table.js”以显示。 如果父组件中有该表,则它可以正常工作,但当我将该表移动到其自己的组件时,会出现一个错误,即forms.map不是函数`TypeError:forms.map不是函数 下面是我的父组件代码MainScreen.js import React, { u
import React, { useEffect, useState } from "react";
import Table from "@material-ui/core/Table";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import TableCell from "@material-ui/core/TableCell";
import TableBody from "@material-ui/core/TableBody";
import Paper from "@material-ui/core/Paper";
import { makeStyles } from "@material-ui/core/styles";
import { useHistory } from "react-router-dom";
const useStyles = makeStyles({
root: {
width: "100%",
overflowX: "auto"
},
table: {
minWidth: 650
}
});
const MyTable = forms => {
let history = useHistory();
const classes = useStyles();
//const forms = useForms("yVhc97ImwzFRz6Kh7Mbn");
console.log("Table Page forms: ", forms);
const openViewDisclaimerPage = row => {
history.push("/viewform", { ...row });
};
return (
<Paper className={classes.root}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Child Name</TableCell>
<TableCell>Time in</TableCell>
<TableCell>Time out</TableCell>
<TableCell>Parent Name</TableCell>
<TableCell>shoe Box Number</TableCell>
</TableRow>
</TableHead>
<TableBody>
{forms.map(row => (
<TableRow
hover
onClick={() => openViewDisclaimerPage(row)}
key={row.id}>
<TableCell component={"th"} scope={"row"}>
{row.children &&
row.children.length &&
row.children[0].childName}
</TableCell>
<TableCell>{row.timeIn}</TableCell>
<TableCell>{row.timeOut}</TableCell>
<TableCell>{row.parentName}</TableCell>
<TableCell>{row.shoeBoxNumber}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Paper>
);
};
export default MyTable;
`
函数主屏幕(){
const[forms,setForms]=useState([]);
让历史=使用历史();
useffect(()=>{
const fetchData=async()=>{
const unsubscribe=等待firebase
.firestore()
.托收(“”)
.doc(“”)
.托收(“”)
.onSnapshot(快照=>{
const newForms=snapshot.docs.map(doc=>({
id:doc.id,
…文件数据()
}));
集合形式(新形式);
});
return()=>unsubscribe();
};
fetchData();
}, []);
const openSignFormPage=()=>{
历史。推送(“/”);
};
控制台日志(“主屏幕窗体:”,窗体);
返回(
{!forms.length?正在加载:}
签署表格
创建/编辑表单
);
}
导出默认主屏幕;
表js的代码
import React, { useEffect, useState } from "react";
import Table from "@material-ui/core/Table";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import TableCell from "@material-ui/core/TableCell";
import TableBody from "@material-ui/core/TableBody";
import Paper from "@material-ui/core/Paper";
import { makeStyles } from "@material-ui/core/styles";
import { useHistory } from "react-router-dom";
const useStyles = makeStyles({
root: {
width: "100%",
overflowX: "auto"
},
table: {
minWidth: 650
}
});
const MyTable = forms => {
let history = useHistory();
const classes = useStyles();
//const forms = useForms("yVhc97ImwzFRz6Kh7Mbn");
console.log("Table Page forms: ", forms);
const openViewDisclaimerPage = row => {
history.push("/viewform", { ...row });
};
return (
<Paper className={classes.root}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Child Name</TableCell>
<TableCell>Time in</TableCell>
<TableCell>Time out</TableCell>
<TableCell>Parent Name</TableCell>
<TableCell>shoe Box Number</TableCell>
</TableRow>
</TableHead>
<TableBody>
{forms.map(row => (
<TableRow
hover
onClick={() => openViewDisclaimerPage(row)}
key={row.id}>
<TableCell component={"th"} scope={"row"}>
{row.children &&
row.children.length &&
row.children[0].childName}
</TableCell>
<TableCell>{row.timeIn}</TableCell>
<TableCell>{row.timeOut}</TableCell>
<TableCell>{row.parentName}</TableCell>
<TableCell>{row.shoeBoxNumber}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Paper>
);
};
export default MyTable;
import React,{useffect,useState}来自“React”;
从“@物料界面/核心/表格”导入表格;
从“@material ui/core/TableHead”导入表头;
从“@material ui/core/TableRow”导入TableRow;
从“@material ui/core/TableCell”导入TableCell;
从“@material ui/core/TableBody”导入表体;
从“@material ui/core/Paper”导入纸张;
从“@material ui/core/styles”导入{makeStyles}”;
从“react router dom”导入{useHistory};
const useStyles=makeStyles({
根目录:{
宽度:“100%”,
overflowX:“自动”
},
表:{
最小宽度:650
}
});
const MyTable=forms=>{
让历史=使用历史();
const classes=useStyles();
//const forms=useForms(“yVhc97ImwzFRz6Kh7Mbn”);
日志(“表页表单:”,表单);
const openViewDisclaimerPage=行=>{
history.push(“/viewform”,{……行});
};
返回(
子名称
时间
时间到
父名称
鞋盒编号
{forms.map(行=>(
openViewDisclaimerPage(行)}
key={row.id}>
{row.children&&
行、子行、长度&&
row.children[0].childName}
{row.timeIn}
{row.timeOut}
{row.parentName}
{row.shoeBoxNumber}
))}
);
};
导出默认MyTable;
当稍微更改代码以尝试不同的方法时,它会呈现加载,然后数据就准备好了,但不会重新呈现,只是停留在加载屏幕上
非常感谢您的帮助。您使用道具的语法错误:
constmytable=forms=>{
...
}
应该是:
constmytable=({forms})=>{
您也不会从useffect()
回调返回unsubscribe。它应该是:
useffect(()=>{
...
返回fetchData();
}, []);
或者您甚至可以删除fetchData()
并使用它的主体:
useffect(()=>{
const unsubscribe=等待firebase
.firestore()
.托收(“”)
.doc(“”)
.托收(“”)
.onSnapshot(快照=>{
const newForms=snapshot.docs.map(doc=>({
id:doc.id,
…文件数据()
}));
集合形式(新形式);
});
return()=>unsubscribe();
}, []);
const MyTable=({forms})=>
您在这里获得了道具,需要解构。如上所述,从道具解构表单,然后条件呈现forms?forms.map(…):没有表单数据!
@colburton是的!谢谢:)我想这是我对react的理解不足。我刚要指出的是,它显示了加载屏幕,然后按照它应该的方式呈现子组件,但是它说forms.map不是一个函数,所以在这一点上,我知道它不再是一个函数数据加载问题。谢谢,我可以用什么来找出问题所在?@colburton是否要添加您的评论作为答案,以便我可以接受。谢谢您的回答,正如@colburton在上面的评论中所说,我需要const MyTable=({forms})=>为了解构,这对我来说很有效。我刚才对你答案的第二部分有个问题。在调用Wait之前,你不需要在函数中使用async吗?我尝试过使用Effect代码,但遇到一个错误,说Wait,必须在异步函数中,我知道这是必须的。你是对的,我错过了你在那里进行的Wait。我的答案是关于highligh的ting您可能在取消订阅时遇到问题,因为您没有为useffect()
callback返回此函数