Обновление Firebase Документы задерживаются на одно событие onClick

Использование react.js и firebase

Код ниже представляет собой простую кнопку, которая увеличивает/уменьшает +1/-1 при каждом нажатии. Он также обновляет один из документов на бэкэнде (используя firebase). Кажется, что все работает нормально на поверхности, но не на firebase. Когда вы нажимаете кнопку, она показывает +1 в пользовательском интерфейсе и console.info, но не в firebase. Другими словами, когда состояние plusCount равно 0, оно показывает +1 в firebase, а когда состояние plusCount равно +1, оно показывает 0 в firebase. Как я могу исправить это, чтобы убедиться, что он показывает один и тот же номер на внешнем и внутреннем интерфейсе? Я также добавил компонент хука useFirestore ниже, где-то может быть ошибка, о которой я не знаю.

Спасибо за любую помощь.

Компонент кнопки:

import React, { useState } from 'react';
import { useFirestore } from "../../hooks/useFirestore"

export default function Testing({ doc }) {
    const { updateDocument } = useFirestore('projects')
    const [plusActive, setPlusActive] = useState(false)
    const [plusCount, setPlusCount] = useState(0)

    function p() {
        setPlusActive(prevState => !prevState);
        plusActive ? setPlusCount(plusCount - 1) : setPlusCount(plusCount + 1)
    }

    const handlePlus = (e) => {
        e.preventDefault();
        p();
        updateDocument(doc.id, {
            votes: plusCount
        })
    }
    console.info(plusCount)

    return (
        <div>
            <button onClick = {handlePlus}>like | {plusCount}</button>
        </div>
    )
} 

Компонент ловушки useFirestore:

import { projectFirestore, timestamp } from "../firebase/config"

let initialState = {
  document: null,
  isPending: false,
  error: null,
  success: null,
}

const firestoreReducer = (state, action) => {
  switch (action.type) {
    case 'IS_PENDING':
      return { isPending: true, document: null, success: false, error: null }
    case 'ADDED_DOCUMENT':
      return { isPending: false, document: action.payload, success: true, error: null }
    case 'DELETED_DOCUMENT':
      return { isPending: false, document: null, success: true, error: null }
    case 'ERROR':
      return { isPending: false, document: null, success: false, error: action.payload }
    case "UPDATED_DOCUMENT":
      return { isPending: false, document: action.payload, success: true, error: null }
    default:
      return state
  }
}

export const useFirestore = (collection) => {
  const [response, dispatch] = useReducer(firestoreReducer, initialState)
  const [isCancelled, setIsCancelled] = useState(false)

  // collection ref
  const ref = projectFirestore.collection(collection)

  // only dispatch if not cancelled
  const dispatchIfNotCancelled = (action) => {
    if (!isCancelled) {
      dispatch(action)
    }
  }

  // add a document
  const addDocument = async (doc) => {
    dispatch({ type: 'IS_PENDING' })

    try {
      const createdAt = timestamp.fromDate(new Date())
      const addedDocument = await ref.add({ ...doc, createdAt })
      dispatchIfNotCancelled({ type: 'ADDED_DOCUMENT', payload: addedDocument })
    }
    catch (err) {
      dispatchIfNotCancelled({ type: 'ERROR', payload: err.message })
    }
  }

  // delete a document
  const deleteDocument = async (id) => {
    dispatch({ type: 'IS_PENDING' })

    try {
      await ref.doc(id).delete()
      dispatchIfNotCancelled({ type: 'DELETED_DOCUMENT' })
    }
    catch (err) {
      dispatchIfNotCancelled({ type: 'ERROR', payload: 'could not delete' })
    }
  }

  // update a document
  const updateDocument = async (id, updates) => {
    dispatch({ type: "IS_PENDING" })

    try {
      const updatedDocument = await ref.doc(id).update(updates)
      dispatchIfNotCancelled({ type: "UPDATED_DOCUMENT", payload: updatedDocument })
      return updatedDocument
    }
    catch (error) {
      dispatchIfNotCancelled({ type: "ERROR", payload: error })
      return null
    }
  }

  useEffect(() => {
    return () => setIsCancelled(true)
  }, [])

  return { addDocument, deleteDocument, updateDocument, response }

}```
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
42
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для вашего варианта использования вы должны useEffect() прослушать изменения для plusCount. См. код ниже:

  useEffect(() => {
    updateDocument('test', {
      votes: plusCount
    })
  }, [plusCount]);

  const handlePlus = (e) => {
      e.preventDefault();
      setPlusActive(prevState => !prevState);
      plusActive ? setPlusCount(plusCount - 1) : setPlusCount(plusCount + 1)
  }

Каждый раз, когда вы нажимаете кнопку, он будет прослушивать изменения plusCount, которые затем также будут запускаться updateDocument вместе с обновленным состоянием. Смотрите ниже скриншот для результата:

Как видите, frontend и backend теперь выровнены.

Вы можете найти дополнительную информацию, проверив этот документация.

Другие вопросы по теме