我有下面的react组件,它创建一个新的文档ref,然后使用useFirestoreDocData钩子订阅它。
由于某种原因,这个钩子在组件中触发了一个无限的reender循环。
有人能看到问题的原因吗?
import * as React from 'react';
import { useFirestore, useFirestoreDocData, useUser } from 'reactfire';
import 'firebase/firestore';
import 'firebase/auth';
import { useEffect, useState } from 'react';
import { Link, useHistory } from 'react-router-dom';
interface ICreateGameProps {
}
interface IGameLobbyDoc {
playerOne: string;
playerTwo: string | null;
}
const CreateGame: React.FunctionComponent<ICreateGameProps> = (props) => {
const user = useUser();
const gameLobbyDocRef = useFirestore()
.collection('GameLobbies')
.doc()
//This for some reason triggers an infinite loop
const { status, data } = useFirestoreDocData<IGameLobbyDoc>(gameLobbyDocRef);
const [newGameId, setNewGameId] = useState('')
const history = useHistory();
useEffect(() => {
async function createGameLobby() {
const gl: IGameLobbyDoc = {
playerOne: user.data.uid,
playerTwo:null
}
if (user.data.uid) {
const glRef = await gameLobbyDocRef.set(gl)
setNewGameId(gameLobbyDocRef.id)
}
}
createGameLobby()
return () => {
gameLobbyDocRef.delete();
}
}, [])
return <>
<h2>Gameid : {newGameId}</h2>
<p>Waiting for second player to join...</p>
<Link to="/">Go Back</Link>
</>
};
export default CreateGame;
问题是当您在没有参数的情况下调用doc()
时:
- firestore每次都会使用新的自动生成的id创建新的文档引用
- 您将此引用传递给负责创建和观察此文档的
useFirestoreDocData
useFirestoreDocData
向服务器发出通知新的草稿文档的请求- 服务器用ok ish响应来响应这个请求(没有id冲突,数据库是可访问的,等等(
- 已创建的观察者更新已创建文档的状态
- 触发重新发布(因为文档数据已经更新(
- 在新的转发器
.doc()
上创建新的文档引用 - 将其提供给
useFirestoreDocData
并且
我相信你已经明白了。
为了打破这个不幸的循环,我们应该确保.doc()
调用在第一次渲染时只发生一次,并且它创建的ref在每次重新渲染时都不会更改。这正是useRef
的作用:
...
const gameLobbyDocRef = React.useRef(useFirestore()
.collection('GameLobbies')
.doc())
const { status, data } = useFirestoreDocData<IGameLobbyDoc>(gameLobbyDocRef.current);
...