一旦moveToResults()
被填满,我就很难弄清楚如何触发setArr(list)
函数。我觉得应该有一种使用new Promise
的简单方法,但是我似乎无法弄清楚。
const [arr, setArr] = useState([]);
const handlePress = ()=>{
var list = [];
firebase.firestore().collection('PostedFunEvents').where("location", "==" , place).get().then((querySnapshot) =>{
querySnapshot.forEach((doc) =>{
list.push(doc.data());
})
setArr(list);
}).then(()=>{
console.log(arr.length);
}).then(()=>{
moveToResults(); // AT THIS POINT ARR.LENGTH IS STILL 0
});
}
这是我的moveToResults()
函数:
const moveToResults = () =>{
navigation.navigate('Results', {arr: arr})
}
问题
如何确保moveToResults()
一经完成就setArr(list)
触发?
我基本上想确保在触发moveToResults()
时填充arr
。否则,我什么都不传递到下一个屏幕。
答案 0 :(得分:1)
使用querySnapshot.docs
返回的数组设置状态:
const [arr, setArr] = useState([]);
// This callback will be called after 'arr' get elements.
React.useEffect(() => {
if (arr.length > 0) {
moveToResults(arr); // go!
}
}, [arr]);
const handlePress = () => {
firebase.firestore().collection('PostedFunEvents').where("location", "==" , place).get()
.then((querySnapshot) => {
console.log(querySnapshot.docs); // debug array
setArr(querySnapshot.docs); // setting list
// moveToResults(querySnapshot.docs); // go!
});
}
答案 1 :(得分:1)
为什么不使用redux,在这种情况下会有很大帮助?
无论如何我在想,是这样的:
const [arr, setArr] = useState([]);
const handlePress = () => {
firebase.firestore()
.collection('PostedFunEvents')
.where("location", "==" , place)
.get()
.then(snapshot => {
let list = [];
if (snapshot.empty) {
throw new Error('No location here.');
}
snapshot.forEach(doc => {
list.push(doc);
});
if (snapshot.length === list.length) {
setArr(list)
}
})
.catch(err => {
console.log('Error getting documents', err);
});
}
我希望它会有所帮助,或者至少它会起作用
答案 2 :(得分:0)
您可以在Firebase操作完成中使用异步等待,而不是使用多个.then()
块
firebase.firestore().collection('PostedFunEvents').where("location", "==" , place).get().then(async (querySnapshot) =>{
await querySnapshot.forEach((doc) =>{
list.push(doc.data());
})
setArr(list);
})
.catch(err=>{
console.log(err)
})
答案 3 :(得分:0)
arr
变量将不会填充,直到您的组件重新渲染为止,因此您不能在同一promise链中调用moveToResults
。但是,这应该是在填充arr
然后调用函数时进行的简单检查。
const [arr, setArr] = useState([]);
useEffect(() => {
if (arr.length > 0) {
moveToResults(arr);
}
}, [arr])
const handlePress = ()=>{
var list = [];
firebase.firestore().collection('PostedFunEvents').where("location", "==" , place).get().then((querySnapshot) =>{
querySnapshot.forEach((doc) =>{
list.push(doc.data());
})
// Use concat because it returns a new array which will allow react to detect a state change
setArr(arr.concat(list));
});
}
答案 4 :(得分:0)
我们可以编写自定义函数,如果状态发生任何变化,它将调用callBack函数
然后您可以从回调中触发函数
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const useStateCallbackWrapper = (initilValue, callBack) => {
const [state, setState] = useState(initilValue);
useEffect(() => callBack(state), [state]);
return [state, setState];
};
const callBack = state => {
console.log("---------------", state);
};
function App() {
const [count, setCount] = useStateCallbackWrapper(0, callBack);
return (
<div className="App">
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>+</button>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
答案 5 :(得分:0)
尝试这个家伙。只有在列表可用后,才应调用setArr和导航。
const handlePress = async () => {
const myPromise = new Promise((resolve, reject) => {
const list = [];
firebase
.firestore()
.collection('PostedFunEvents')
.where("location", "==", place)
.get()
.then((querySnapshot) => {
querySnapshot.forEach(doc =>
list.push(doc.data()
));
resolve(list);
}).catch(reject);
});
try {
const myList = await myPromise();
console.log(myList);
setArr(list);
navigation.navigate('Results', {arr: myList});
} catch (e) {
console.log(e)
}
}