useEffect переопределяет состояние вместо добавления значений при выполнении вызовов firestore - PullRequest
0 голосов
/ 01 августа 2020
const [data, setData] = useState([])
    
     const getDataFromFirebase = async () => {
         let response = await firestore.collection('someDatabase').get()
         response.forEach(item => setData([...data, item.data().name]))
         
     }
    
    useEffect(() => {
       getDataFromFirebase()
    },[])

данные заменяются последним значением вместо добавления всех значений в массив.

Ответы [ 5 ]

1 голос
/ 01 августа 2020

Причина в том, что время, затраченное на добавление элемента, очень мало, поэтому перед отражением оно было отменено. Вы должны использовать prevState в setData. Попробуйте это:

const [data, setData] = useState([])

const getDataFromFirebase = async () => {
let response = await firestore.collection('someDatabase').get()
response.forEach(item => setData(prevState => ([
    ...prevState, item.data().name])
  );
}
useEffect(() => {
  getDataFromFirebase()
  },[])
1 голос
/ 01 августа 2020
let response = await firestore.collection('someDatabase').get()
response.forEach(item => setData([...data, item.data().name]))

Я не знаком с firestore, но это обещание будет выполнено один раз, и вместо этого вы должны сделать что-то вроде этого:

const dataToAdd = response.map(item => item.data().name)
setData(prevState => ([...prevState, ...dataToAdd])

Вы обновляете компонент каждый раз, когда * Вызывается 1006 *, и вам не следует делать это в синхронизированном l oop.

prevState необходимо здесь, потому что вы работаете в асинхронной функции. Теоретически он должен работать без него после использования решения с dataToAdd, если вы не измените состояние где-либо еще.

1 голос
/ 01 августа 2020

Используйте обратный вызов в setData

setData(prevState => ([
    ...prevState, item.data().name
]));
0 голосов
/ 01 августа 2020

В вашем коде ниже значение данных всегда будет [], даже если вы измените данные позже.

const getDataFromFirebase = async () => {
         let response = await firestore.collection('someDatabase').get()
         response.forEach(item => setData([...data, item.data().name]))
         
     }

Это то, что об этом говорят документы

Мутации, подписки, таймеры, ведение журнала и другие побочные эффекты не допускаются внутри основного тела функционального компонента (называемого фазой рендеринга React). Это приведет к сбивающим с толку ошибкам и несоответствиям в пользовательском интерфейсе.

Не рекомендуется вызывать setData в каждом l oop. Заполните массив и передайте его в setData после завершения l oop.

     const getDataFromFirebase = async () => {
         let response = await firestore.collection('someDatabase').get();
         let newData = [];
         response.forEach(item => newData.push(item.data().name));

         // now set the new data
         setData(prevData=> ([...prevData, ...newData]));
         
         // or you can use Array.concat
         // setData(prevData=> (prevData.concat(newData)));
     }
0 голосов
/ 01 августа 2020

попробуйте этот запуск setState один раз, но сначала создайте массив:

const [data, setData] = useState([])
    
 const getDataFromFirebase = async () => {
    let response = await firestore.collection('someDatabase').get()
    const d = response.map(item=> item.data().name)
    setData(d)  
  }
    
 useEffect(() => {
       getDataFromFirebase()
 },[])

запуск setData несколько раз вызовет несколько повторных рендеров, поэтому здесь он запускается один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...