Home > Mobile >  why isn't my array being rendered on my page?
why isn't my array being rendered on my page?

Time:01-03

I am trying to render listed property information from an array of objects. I used this method in another part of my project with success, but in this instance, I am not getting anything at all.

here is the code I have

import { database } from "../../components/firebase";
import { ref, child, get } from "firebase/database";
import { useState, useEffect } from "react";

export default function Dashboard() {
  const dbRef = ref(database);
  const [users, setUsers] = useState([]);
  const array = [];

  const getData = () => {
    get(child(dbRef, "users/"))
      .then((snapshot) => {
        const data = snapshot.val();
        setUsers(data);
      })
      .catch((err) => {
        console.log(err);
      });
  };

  const getProperties = () => {
    Object.values(users).forEach((user) => {
      Object.values(user?.properties).forEach((property) => {
        array.push(property);
        console.log(property);
      });
    });
    console.log(array);
  };
  useEffect(() => {
    getData();
    getProperties();
  }, [dbRef]);

  return (
    <>
      <div>Properties </div>
      <div>
        {array.map((property) => (
          <div key={property.property_id}>
            <h1>{property?.property_name}</h1>
            <p>{property?.description}</p>
            <p>{property?.rooms}</p>
            <p>{property?.phone}</p>
          </div>
        ))}
      </div>
      <p>oi</p>
    </>
  );
}

Nothing happens, it only prints "properties" and "oi"

CodePudding user response:

getData is asynchronous. When you execute getProperties, your users state will still be its initial, empty array value.

You don't appear to be using users for anything else but assuming you want to keep it, the easiest way to drive some piece of state (array) from another (users) is to use a memo hook.

// this is all better defined outside your component
const usersRef = ref(database, "users");
const getUsers = async () => (await get(usersRef)).val();

export default function Dashboard() {
  const [users, setUsers] = useState({}); // initialise with the correct type

  // Compute all `properties` based on `users`
  const allProperties = useMemo(
    () =>
      Object.values(users).flatMap(({ properties }) =>
        Object.values(properties)
      ),
    [users]
  );

  // Load user data on component mount
  useEffect(() => {
    getUsers().then(setUsers);
  }, []);

  return (
    <>
      <div>Properties </div>
      <div>
        {allProperties.map((property) => (
          <div key={property.property_id}>
            <h1>{property.property_name}</h1>
            <p>{property.description}</p>
            <p>{property.rooms}</p>
            <p>{property.phone}</p>
          </div>
        ))}
      </div>
      <p>oi</p>
    </>
  );
}

The memo hook will recompute allProperties any time users is changed.


If you don't need the users state, then there's not much need for the memo hook. Instead, just maintain the state you do need

const [allProperties, setAllProperties] = useState([]); // init with empty array

useEffect(() => {
  getUsers().then((users) => {
    setAllProperties(
      Object.values(users).flatMap(({ properties }) =>
        Object.values(properties)
      )
    );
  });
}, []);
  • Related