【发布时间】:2020-11-02 13:44:15
【问题描述】:
我一直在查看很多问题/答案以及流星文档,但仍然无法使用流星反应并等待订阅的数据完全加载。我正在尝试做两件不同的事情,一件是如果从数据库收到的数组小于在客户端创建的数组,然后做其他事情,如果它更大或相等。
问题在于我的订阅,数据有时会被管道传输,所以第一条语句总是至少触发一次。
我想知道在调用函数之前是否有办法确保数据库中的所有数据都已通过。
if (import.length < arrayLength) {
...
}
if (import.length > arrayLength || import.length === arrayLength) {
...
}
下面的完整代码示例
import { DropzoneDialog } from "material-ui-dropzone";
import React, { useState, useEffect, useRef } from "react";
import Button from "@material-ui/core/Button";
import { Cards } from "../../../../both/collections";
import { withTracker } from "meteor/react-meteor-data";
import { makeStyles } from "@material-ui/core/styles";
import { Meteor } from 'meteor/meteor';
import _, { map, object } from 'underscore';
const useStyles = makeStyles({
importButton: {
color: "#C8C8C8",
borderColor: "#C8C8C8",
"&:hover": {
backgroundColor: "rgba(72,72,72,0.7)",
borderColor: "rgba(255, 255, 255)",
color: "rgba(255, 255, 255)",
},
},
});
function importDeck(files, setDeckIsReady, setDeckLength, setCountObj, sub, setSubscription) {
let reader = new FileReader();
reader.readAsText(files[0]);
reader.onload = function () {
let cardArray = reader.result.split("\n");
let cardArrayFiltered = cardArray.filter(Boolean)
const countObj = cardArrayFiltered.reduce((acc, next) => {
count = next.substr(0, next.indexOf(' '));
name = next.substr(next.indexOf(' ') + 1);
return {...acc, [name]: count}
}, {});
sub.stop()
const subscription = Meteor.subscribe('cardSearchTwo', Object.keys(countObj), {onReady() {setDeckIsReady(true)}})
setDeckLength(Object.keys(countObj).length)
setCountObj(countObj)
setSubscription(subscription)
};
}
export function DeckImport({importCards, setCurrentDeck, importDeckFinal, search, setSearch}) {
const classes = useStyles()
const [open, setOpen] = useState(false);
const [deckIsReady, setDeckIsReady] = useState(false);
const [deckLength, setDeckLength] = useState(0);
const [countObj, setCountObj] = useState({});
const [subscription, setSubscription] = useState({stop(){}})
const [isReady, setIsReady] = useState(false)
console.log(deckIsReady, importCards)
let missingCards = []
let fixedDeck = importCards
useEffect(() => {
if (importCards.length < deckLength && deckIsReady) {
fixedDeck = []
Object.keys(countObj).forEach(card => {
if (!importCards.some(e => e.name === card)) missingCards.push(card)
})
fixedDeck = importCards.filter(card => !missingCards.includes(card.name))
console.log('LESS THAN', fixedDeck.length, missingCards.length)
importDeckFinal(fixedDeck, setCurrentDeck, countObj)
setDeckIsReady(false)
setDeckLength(0)
setCountObj({})
}
if ((importCards.length > deckLength || importCards.length === deckLength) && deckIsReady) {
fixedDeck = []
importCards.forEach(card => {
if (card.name in countObj) fixedDeck.push(card)
})
console.log('EQUAL', fixedDeck);
importDeckFinal(fixedDeck, setCurrentDeck, countObj)
setDeckIsReady(false)
setDeckLength(0)
setCountObj({})
}
})
return (
<div>
<Button
variant="outlined"
color="primary"
component="label"
onClick={() => setOpen(true)}
className={classes.importButton}>
Import
</Button>
<DropzoneDialog
acceptedFiles={["text/*"]}
cancelButtonText={"cancel"}
submitButtonText={"submit"}
maxFileSize={5000000}
open={open}
onClose={() => setOpen(false)}
onSave={(files) => {
importDeck(
files,
setDeckIsReady,
setDeckLength,
setCountObj,
subscription,
setSubscription,
setIsReady
);
setOpen(false);
}}
showPreviews={true}
showFileNamesInPreview={true}
/>
</div>
)
}
export default withTracker(props => {
const cards = Cards.find({}, { sort: {name: 1}}).fetch();
const uniqueNames = _.uniq(cards.map(function(x) {return x.name;}), true)
return {
importCards: uniqueNames.map(name => cards.find(({ name: cName }) => cName === name))
};
})(DeckImport);
具体来说,deckIsReady 被设置为 True 当只有一部分数据真正准备好时。
【问题讨论】:
-
您可以使用方法从服务器获取数据。逻辑比使用订阅更简单,性能更好。
标签: javascript reactjs meteor