道具准备好之前的子组件渲染
Child component rendering before props are ready
我很确定我知道问题所在。我认为这是因为子组件在其道具准备好之前渲染。在看了很多教程和文档之后,我就是想不通我做错了什么。
我正在使用挂钩和 useEffect 在页面打开时从 firestore 获取数据。之后,我想将数据传递给子组件 "Table.js" 进行显示。
如果我在父组件中有 table 它工作正常,但是一旦我将 table 移动到它自己的组件我得到一个错误说 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;
当稍微更改代码以尝试不同的方法时,它会呈现加载,然后数据准备就绪,但不会重新呈现,只是停留在加载屏幕上。
非常感谢任何帮助。
你使用 props 的语法错误:
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();
}, []);
我很确定我知道问题所在。我认为这是因为子组件在其道具准备好之前渲染。在看了很多教程和文档之后,我就是想不通我做错了什么。
我正在使用挂钩和 useEffect 在页面打开时从 firestore 获取数据。之后,我想将数据传递给子组件 "Table.js" 进行显示。 如果我在父组件中有 table 它工作正常,但是一旦我将 table 移动到它自己的组件我得到一个错误说 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;
当稍微更改代码以尝试不同的方法时,它会呈现加载,然后数据准备就绪,但不会重新呈现,只是停留在加载屏幕上。
非常感谢任何帮助。
你使用 props 的语法错误:
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();
}, []);