Pepe
Pepe

Reputation: 515

How to render user list in React-Firebase

I'm still learning React and I'm trying to make a "design review app" where users signup as customers or designers and interact with each other. I made the auth system and made sure that while signing up every user would get also some attributes in the firebase database. Therefore, in my DB, I have a 'users/' path where every user is saved by uid. structure

Now I'm able to render a different dashboard if you're a customer or a designer. In my customer dashboard, I just want to render a list of designers (and clicking on them go to their projects). However, I'm having so many problems trying to get this stuff to work!

In the following code, I'm trying to fetch the users from the db and add their uid to an array. Later I want to use this array and render the users with those uids.

import firebase from "firebase/app";
import "firebase/database";

export default function CustomerContent() {
    const[designers, setDesigners] = useState([]);

    function printUsers (){
        var users = firebase.database().ref('/users/');
        users.on('value', (snapshot)=>{
            snapshot.forEach((user)=>{
                console.log(user.key) 
                firebase.database().ref('/users/'+user.key).on('value', (snapshot)=>{
                    var role = snapshot.val().role
                    console.log(role)
                    if(role === 'designer'){
                        const newDesigners = [...designers, user.key];
                        setDesigners(newDesigners);
                    }
                })
            })
        })
    }
    useEffect(() => {
        printUsers();
        console.log(designers);

    }, [])

    return (
        <div>
            designer list
        </div>
    )
}

Now the problem with this code is that:

  1. it looks like it runs the printUsers functions two times when loading the page
  2. the array is empty, however, if I link the function to a button(just to try it), it seems to add only 1 uid to the array, and always the same (I have no idea what's going on).

ps. the console.log(user.key) and the console.log(role) print the right user-role combination

Upvotes: 1

Views: 3133

Answers (1)

David Frederick
David Frederick

Reputation: 202

It's not a stupid question. Here's what I'd change it to (of course you'd remove the console.logs later though). It's hard to know if this will work perfectly without having access to your database to run it, but based on my last react/firebase project, I believe it'll work.

The first thing was that you reference /users/, when you only need /users. I'm not sure if it makes a difference, but I did it the latter way and it worked for me.

Secondly, you're calling firebase more than you need to. You already have the information you need from the first time.

Third, and this is small, but I wouldn't call your function printUsers. You're doing more than just printing them- you're making a call to firebase (async) and you're setting the state, which are much larger things than just print some data to the console.

Lastly, I would store the entire object in your designers piece of state. Who knows what you'll want to display? Probably at least their name, then possibly their location, background, an icon, etc. You'll want all of that to be available in that array, and possibly you'll want to move that array into redux later if you're app is big enough.

I also added some JSX to the bottom that gives a simple output of what you could do with the designers array for the visual aspect of your app.

import firebase from 'firebase/app';
import 'firebase/database';

export default function CustomerContent() {
    const [designers, setDesigners] = useState([]);

    function printUsers() {
        var users = firebase.database().ref('/users');
        users.on('value', (snapshot) => {
            snapshot.forEach((snap) => {
                const userObject = snap.val();
                console.log(userObject);
                const role = userObject['role'];
                console.log(role);
                if (role === 'designer') {
                    const newDesigners = [...designers, userObject];
                    setDesigners(newDesigners);
                }
            });
        });
    }
    useEffect(() => {
        printUsers();
        console.log(designers);
    }, []);

    return (
        <div>
            <h2>The designer are...</h2>
            <ul>
                {designers.map((designerObject) => {
                    return <li>{designerObject.name}</li>;
                })}
            </ul>
        </div>
    );
}

Upvotes: 3

Related Questions