Javascript 道具准备就绪之前的子组件渲染

Javascript 道具准备就绪之前的子组件渲染,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

我相当肯定我知道这个问题。我认为这是因为在道具准备好之前子组件渲染。在看了很多教程和文档之后,我就是不知道我做错了什么

当页面打开时,我使用钩子和useEffect从firestore获取数据。之后,我想将数据传递给子组件“Table.js”以显示。 如果父组件中有该表,则它可以正常工作,但当我将该表移动到其自己的组件时,会出现一个错误,即forms.map不是函数`TypeError:forms.map不是函数

下面是我的父组件代码MainScreen.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;
`

函数主屏幕(){
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返回此函数