0

I have a react component with a selector that gets some state from a firebase database. However, in the useEffect of my component that has this state as a dependency, it only ever returns an empty array even though the Redux dev tools shows me that the state has updated. The console also prints the empty array but when I expand it the array is updated. What could be happening?

Minimal version of my component:

const PatientsPage = () => {
  const dispatch = useDispatch();
  const invitedPatients = useSelector((state) => state.invitations.invitedPatients);

  useEffect(() => {
    console.log("in use effect invited patients", invitedPatients);
    // console prints empty array but when I expand it
    // it is populated yet this function isn't triggered again to set the new value for rendering
  }, [invitedPatients]);

  useEffect(() => {
    // this dispatches the invitedPatients action
    dispatch(getInvitations(firebase.auth().currentUser.uid));
  }, []);

}

Here it is in the console, as you can see an empty array is printed yet it's populated in the expanded view:

I don't know what the issue is. I can post my action and reducer functions if needed. Please provide some guidance as to how I can diagnose the problem. Thanks

EDIT: here is the action

export const getInvitations = (doctorId) => {
  const invitationObjects = [];
  const invitedPatients = [];
  return async (dispatch, getState, getFirebase) => {

     ...code to populate my invitationsObjects

      invitationObjects.forEach(async (invitationObject) => {
        const invitedPatient = await getPatient(invitationObject.patientId);
        invitedPatients.push(invitedPatient);
      });

      dispatch({
        type: GET_INVITATIONS_SUCCESS,
        payload: invitedPatients,
      });
    } catch (error) {
      ...
    }
  };
};

And the reducer

const initialState = {
  invitedPatients: null,
  sending: false,
};

export default function invitationsReducer(state = initialState, action) {
  switch (action.type) {
    case "GET_INVITATIONS_SUCCESS":
      return {
        ...state,
        invitedPatients: action.payload,
      };
    
    default:
      return { ...state };
  }
}

This is the getPatient function:

export const getPatient = async (patientId) => {
  try {
    const documentSnapshot = await firestore.collection("patients").doc(patientId).get();
    console.log("getPatient -> documentSnapshot", documentSnapshot.data())
    return documentSnapshot.data();
  } catch(error) {
    console.log(error);
  }
}
skyboyer
  • 22,209
  • 7
  • 57
  • 64
dazzaondmic
  • 345
  • 4
  • 14

1 Answers1

0

The problem is that you can't use an async function in a forEach loop. I changed it to use normal loop notation and it worked.

dazzaondmic
  • 345
  • 4
  • 14
  • You don't need to fetch in series though, you can fetch your data in parallel if you look at [this answer](https://stackoverflow.com/a/37576787). – Patrick Roberts Oct 23 '20 at 18:33