Home > Enterprise >  ReactJS component not re-rending after setState update?
ReactJS component not re-rending after setState update?

Time:10-20

I'm learning about ReactJS hooks and firebase, I'm getting users from the firestore and using the "Verify" button I set the user.status to "verified", This code works to verify the user in the firestore, however I don't know where exactly should I set the state of the user in order to make the component re-render!

I would appreciate your help !

/* some imports have been hidden for making the code readable */
import React, { useState, useEffect } from 'react'


import {db} from '../firebase'
import { collection, getDocs, query, where, updateDoc, doc } from 'firebase/firestore'



export default function Page() {

    const [error, setError] = useState("")
    const { currentUser, logout } = useAuth()
    const[status, setStatus] = useState("notverified")
    const history = useHistory()
    
    // firestore
    const [users, setUsers] = useState([])
    const usersCollectionRef = collection(db, "users")
    const queryInverified = query(usersCollectionRef, where("status","==", "notverified"))



    const updateUser = async (id, status)=> {
      const userDoc = doc(db, "users", id)
      const newStatus = {status: status= "verified"}
      setStatus("verified")
      await updateDoc(userstDoc, newStatus)
      
     /* Following AKX 's answer! */
      setUsers((oldUsers) =>
      oldUsers.map((user) => 
      user.id === id? {...user, status} : user,
       ),
      );
    }
      
    }
    useEffect(() =>{


        const getUsers = async () => {
            const data = await getDocs(queryInverified)
            setUsers(data.docs.map((doc)=>({...doc.data(), id: doc.id})))}

        getUsers()      
    }, [])



    return (
        <>
        <Container>
            <Card>
                <Card.Body>  
                    <div>
                       {users.map((user) => {
                           return(
                            <div className="card mb-4" >
                            <div className="card-body">
                              <h5>User Name: {user.name}</h5>
                              <p>Verification status: {user.status}</p>}                             
                              <Button onClick={() =>{updateUser(user.id, user.status)>
                              Verify</Button>
                              
                            </div>
                          </div>
                           )
                       })}

                    </div>
                </Card.Body>
            </Card>
       </Container> 
      </>
    ) 
}

CodePudding user response:

Well, you're not updating the users state in any way after updating the user in Firebase.

You have about two options:

  • an optimistic update of the local state, i. e. setUsers(...) after the updateDoc await to update the just-updated user in the users array:

    setUsers((oldUsers) =>
      oldUsers.map((user) =>
        user.id === id ? { ...user, status } : user,
      ),
    );
    
  • simply reload the data from Firebase afterwards; refactor that fetching code to another function you can call both in the current useEffect and within the updateUser handler.

CodePudding user response:

Like @AKX mentioned, with the first option you can do this:

setUsers(...usersDoc.data, id)
  • Related