{React Native}一旦状态为最新就触发函数

时间:2020-05-05 04:50:05

标签: reactjs react-native

一旦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。否则,我什么都不传递到下一个屏幕。

6 个答案:

答案 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)
  }
}