我正在尝试使用react useEffect钩子从firestore中获取数据并将其提供给Material UI自动完成选择菜单上的options属性。
我在消防处有一个叫做“组织”的收藏。该文档具有名为“ shortName”的属性。
我正在尝试从集合中获取数据,然后使用它在名为orgList的属性上设置状态,然后可以在选择菜单中的中使用它。
这就是我正在尝试的。
import React, { useState, useEffect } from 'react';
import Checkbox from '@material-ui/core/Checkbox';
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
import CheckBoxIcon from '@material-ui/icons/CheckBox';
import firebase from "../../../../../firebase";
const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;
export default function CheckboxesTags() {
const [orgList, setOrgList] = useState();
const [selectedOrgList, setSelectedOrgList] = useState();
useEffect(() => {
firebase
.firestore()
.collection("organisations")
.onSnapshot(snapshot => {
const orgList = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data(),
}))
setOrgList(orgList)
})
}, [orgList])
return (
<div>
<Autocomplete
multiple
id="checkboxes-tags-demo"
options={orgList}
disableCloseOnSelect
getOptionLabel={(option) => option.shortName}
renderOption={(option, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.shortName}
</React.Fragment>
)}
style={{ width: 500 }}
renderInput={(params) => (
<TextField {...params}
variant="outlined"
label="Select Organisation"
placeholder="Acme Inc"
/>
)}
/>
</div>
);
}
我收到的错误消息是:
TypeError:无法读取未定义的属性'shortName'
下一个尝试
使用下面来自gdh的建议,这是下一次尝试。
import React, { useState, useEffect } from 'react';
import Checkbox from '@material-ui/core/Checkbox';
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
import CheckBoxIcon from '@material-ui/icons/CheckBox';
import firebase from "../../../../../firebase";
const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;
export default function CheckboxesTags() {
const [orgList, setOrgList] = useState([]);
const [selectedOrgList, setSelectedOrgList] = useState();
const [loading, setLoading ] = useState(true);
const [ error, setError ] = useState(false);
useEffect(() => {
const unsubscribe = firebase
.firestore()
.collection("organisations")
.onSnapshot((snapshot) => {
const orgList = snapshot.docs.map((doc) => ({
id: doc.id,
shortName: doc.shortName
}));
console.log(orgList)
setOrgList(orgList);
}, () => {
setError(true)
});
setLoading(false);
return() => unsubscribe();
}, [orgList]);
useEffect(() => {
firebase
.firestore()
.collection("organisations")
.get()
.then((snapshot) => {
const orgList = snapshot.docs.map((doc) => ({
id: doc.id,
shortName: doc.shortName
}));
setOrgList(orgList);
});
}, []);
return (
<div>
<Autocomplete
multiple
id="checkboxes-tags-demo"
options={orgList}
disableCloseOnSelect
getOptionLabel={(orgList) => orgList.shortName}
renderOption={(orgList, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{orgList.shortName}
</React.Fragment>
)}
style={{ width: 500 }}
renderInput={(params) => (
<TextField {...params}
variant="outlined"
label="Select Organisation"
placeholder="Acme Inc."
/>
)}
/>
</div>
);
}
控制台日志显示两个orgList id,但是shortName是未定义的。
我看到一条错误消息:
TypeError:无法读取未定义的属性“ toLowerCase”。
为解决此错误,我添加了:
ignoreCase = {false}
到“自动完成”标题标签,但仍然存在相同的错误。控制台会记录一条错误消息:
警告:React无法识别DOM上的
ignoreCase
道具 元件。如果您有意让它作为自定义项出现在DOM中 属性,则将其拼写为小写ignorecase
。如果你 意外地从父组件传递了它,将其从DOM中删除 元素
我尝试将Firestore中的shortName重命名为'short',以查看是否可以避免区分大小写的问题,但是仍然存在相同的错误(控制台在Firestore控制台中具有值时,其简短记录为undefined)。
我知道表单是从firestore中读取的,因为当我尝试将选项设置为文档的id时,表单会加载,并且id将打印为值。
答案 0 :(得分:0)
orgList
的初始值。提供一个空白数组。onSnapshot
回调,该回调仅在organisations
集合更改时执行,但您未在装入时获取任何数据。这意味着仅当有人在organisation
集合中进行更改时,您的自动填充功能才会具有值。因此,请保持另一个useEffect并获取数据。重构代码
export default function CheckboxesTags() {
const [orgList, setOrgList] = useState([]);
const [selectedOrgList, setSelectedOrgList] = useState();
useEffect(() => {
firebase
.firestore()
.collection("organisations")
.onSnapshot((snapshot) => {
const orgList = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setOrgList(orgList);
});
}, []);
useEffect(() => {
firebase
.firestore()
.collection("organisations")
.get()
.then((snapshot) => {
const orgList = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setOrgList(orgList);
});
}, []);
//.... rest of code...
答案 1 :(得分:0)
我找到了行之有效的方法-最终。似乎存在限制从Firebase文档读取单个属性的问题。在我的快照中,我试图读取:doc.shortName / doc.short。它必须是:
shortName: doc.data().shortName,
我最终并不需要gdh提议的第二个.get useEffect。
这对我有用:
import React, { useState, useEffect } from 'react';
import Checkbox from '@material-ui/core/Checkbox';
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
import CheckBoxIcon from '@material-ui/icons/CheckBox';
import firebase from "../../../../../firebase";
const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;
export default function CheckboxesTags() {
const [orgList, setOrgList] = useState([]);
const [selectedOrgList, setSelectedOrgList] = useState();
const [loading, setLoading ] = useState(true);
const [ error, setError ] = useState(false);
useEffect(() => {
// if (doc.exists) {
const unsubscribe = firebase
.firestore()
.collection("organisations")
.onSnapshot((snapshot) => {
const orgList = snapshot.docs.map((doc) => ({
id: doc.id,
shortName: doc.data().shortName
}));
console.log(orgList)
setOrgList(orgList);
}, () => {
setError(true)
});
setLoading(false);
return() => unsubscribe();
}, [orgList]);
// useEffect(() => {
// firebase
// .firestore()
// .collection("organisations")
// .get()
// .then((snapshot) => {
// const orgList = snapshot.docs.map((doc) => ({
// id: doc.id,
// ...doc.data()
// }));
// setOrgList(orgList);
// });
// }, []);
return (
<div>
<Autocomplete
multiple
id="checkboxes-tags-demo"
options={orgList}
disableCloseOnSelect
getOptionLabel={(option) => option.shortName}
renderOption={(orgList, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{orgList.shortName}
</React.Fragment>
)}
style={{ width: 500 }}
renderInput={(params) => (
<TextField {...params}
variant="outlined"
label="Select Organisation"
placeholder="Acme Inc."
/>
)}
/>
</div>
);
}
对于toLowerCase错误-有一个filterOptions属性可用于自动完成功能。我不知道该如何工作-但就目前而言,这又是一个问题。