Search code examples
reactjsfirebasereact-hooksuse-effect

Delete doc on component unmount (React and Firebase)


I have a react component that will create a new document on mounting

const CreateGame: React.FunctionComponent<ICreateGameProps> = (props) => {


    const gamesRef = useFirestore()
        .collection('Games')

    const [newGameId, setNewGameId] = useState('')

    useEffect(() => {
        const newGame: IGameDoc = {
            playerTurn: 'x',
            secondPlayerJoined: false,
            gameState: {
                rowOne: [null, null, null],
                rowTwo: [null, null, null],
                rowThree: [null, null, null]
            }
        }

        gamesRef.add(newGame)
            .then(docRef => setNewGameId(docRef.id))

        return () => {
            gamesRef.doc(newGameId).delete()
        }

    }, [])

however, as soon as the component unmounts again, I would like to delete that same document again, hence I have the cleanup function in my useEffect hook

return () => {
    gamesRef.doc(newGameId).delete()
}

This does not work however. Does anyone know why?


Solution

  • Issue

    It doesn't work because it seems you close over the initial newGameId state which has a value of '' and isn't the docRef.id it's updated to.

    Solution

    Use an additional useRef hook to cache a copy of the newGameId state value and reference this in the useEffect hook's cleanup function.

    const gameIdRef = useRef(); // <-- create a ref to store game id
    const gamesRef = useFirestore().collection('Games');
    
    const [newGameId, setNewGameId] = useState('');
    
    useEffect(() => {
      const newGame: IGameDoc = {
        playerTurn: 'x',
        secondPlayerJoined: false,
        gameState: {
          rowOne: [null, null, null],
          rowTwo: [null, null, null],
          rowThree: [null, null, null]
        }
      }
    
      gamesRef
        .add(newGame)
        .then(docRef => {
          setNewGameId(docRef.id);
          gameIdRef.current = docRef.id; // <-- cache game id
        })
    
      return () => {
        gamesRef.doc(gameIdRef.current).delete(); // <-- access ref's current value
      };
    }, []);