Использование 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 }
}```
Для вашего варианта использования вы должны 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
теперь выровнены.
Вы можете найти дополнительную информацию, проверив этот документация.