道具准备好之前的子组件渲染

时间:2019-12-03 18:25:03

标签: javascript reactjs async-await react-hooks use-effect

我相当确定我知道这个问题。我认为这是因为在准备好道具之前先渲染子组件。看完许多教程和文档后,我只是弄不清楚我在做什么错。

当页面打开时,我正在使用钩子和useEffect从Firestore获取数据。之后,我想将数据传递给子组件“ Table.js”进行显示。 如果我在父组件中有表,则可以正常工作,但是一旦我将表移到其自己的组件中,我就会收到一条错误消息,说Forms.map不是函数`TypeError:Forms.map不是函数

这是我的父组件 MainScreen.js

的代码

`

  function MainScreen() {
  const [forms, setForms] = useState([]);
  let history = useHistory();

  useEffect(() => {
    const fetchData = async () => {
      const unsubscribe = await firebase
        .firestore()
        .collection("")
        .doc("")
        .collection("")
        .onSnapshot(snapshot => {
          const newForms = snapshot.docs.map(doc => ({
            id: doc.id,
            ...doc.data()
          }));

          setForms(newForms);
        });
      return () => unsubscribe();
    };
    fetchData();
  }, []);



  const openSignFormPage = () => {
    history.push("/");
  };

  console.log("MainScreen forms:", forms);

  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        margin: "auto",
        padding: "2% 4%"
      }}>
      {!forms.length ? <div>Loading</div> : <MyTable forms={forms} />}

      <div
        style={{
          border: "solid red 1px",
          display: "flex",
          flexDirection: "row",
          justifyContent: "space-around"
        }}>
        <Button color={"blue"} onClick={openSignFormPage}>
          Sign forms
        </Button>
        <Button color={"blue"}>Create / Edit forms</Button>
      </div>
    </div>
  );
}
export default MainScreen;

Table.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;

稍稍更改代码以尝试使用其他方法时,它会呈现加载状态,然后准备好数据,但不会重新呈现,而是停留在加载屏幕上。

我将非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您使用道具的语法错误:

const MyTable = forms => {
  ...
}

应该是:

const MyTable = ({ forms }) => {

您也不会从useEffect()回调中返回退订。应该是:

useEffect(() => {
  ...
  return fetchData();
}, []);

或者您甚至可以删除fetchData()并改用它的正文:

useEffect(() => {
   const unsubscribe = await firebase
        .firestore()
        .collection("")
        .doc("")
        .collection("")
        .onSnapshot(snapshot => {
          const newForms = snapshot.docs.map(doc => ({
            id: doc.id,
            ...doc.data()
          }));

          setForms(newForms);
        });
      return () => unsubscribe();
  }, []);