prescottprue / react-redux-firebase

Redux bindings for Firebase. Includes React Hooks and Higher Order Components.
https://react-redux-firebase.com
MIT License
2.55k stars 559 forks source link

2.5.1 - not saving user profiles when using firestore #999

Open solveretur opened 3 years ago

solveretur commented 3 years ago

Do you want to request a feature or report a bug?

(If this is a usage question, please do not post it here—post it on gitter. If this is not a “feature” or a “bug”, or the phrase “How do I...?” applies, then it's probably a usage question.)

What is the current behavior?

The userProfile collection - users - is not created in the cloud firestore.

Zrzut ekranu 2020-09-3 o 11 16 13

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via codesandbox or similar.

my code is exactly the same as in the tutorial. I have config like this:

export const reduxFirebase = {
    userProfile: "users",
    useFirestoreForProfile: true
};

What is the expected behavior?

userProfile collection will be created and available in the console of the cloud firestore. It works that way with the real time database

Which versions of dependencies, and which browser and OS are affected by this issue? Did this work in previous versions or setups?

"react-redux-firebase": "2.5.1", "redux-firestore": "^0.13.0",

prescottprue commented 3 years ago

I will have to look, but I'm not sure this was a feature back in the v2 series. Is there a reason you can't be using v3*?

solveretur commented 3 years ago

Thanks a lot. I've found out that the issue is a little bit different than I described. Basically currently I've been moving my firebase app from real time database to the cloud firestore. Currently my react-redux-firebase config looks like that

export const reduxFirebase = {
    userProfile: "users"
};

I exported all the users from the current project and imported them back to the new one then I moved all of the documents under userProfile path /users to the same path in the cloud firestore database. So now in theory I should have the same state of data regarding users and their profiles in both databases.

After I login into my app using my gmail account, which in firebase has some id let's say qWertYzAbcdEfhJijk, when I try to fetch all documents from the firestore under the path /users I can only fetch documents which were created when somebody logged into my app with new config. It doesn't see all the user data I migrated

    export default compose(
        withStyles(styles),
        firestoreConnect(props => [
            {
                collection: "users",
                storeAs: "users"
            },
        ]),
        connect(mapStateToProps, mapDispatchToProps)
    )(ActiveUsersPanel);
...
const mapStateToProps = (state, props) => {
    return {
        users: state.firestore.data.users
    };
};
...
function ActiveUsersPanel(props) {
    const {firebase, classes, users} = props;
    console.log(users);
...

the result contains only one item

{"qWertYzAbcdEfhJijk":{"id":"qWertYzAbcdEfhJijk","avatarUrl":"https://lh6.go...","displayName":"My name","email":"my@email.com","providerData":[{"email":"my@email.com","phoneNumber":null,"photoURL":"https://lh6.googl...","providerId":"google.com","uid":"115418232581098xxxxxx"}]}}

And doesn't contain all of the documents I migrated from the old database even though they look the same I noticed that when I change the react-redux-firebase config to point to other path

export const reduxFirebase = {
           userProfile: "storedUsers",
           useFirestoreForProfile: true
       };

suddenly it's able to read the /users correctly in my component, however the new users are saved under this new path /storedUsers so it doesn't solve my issue - it only implies that the problem is with the way the library reads the user profile path Why is it happening and how to solve it ?

prescottprue commented 3 years ago

You should try using a different storeAs with your users query - the single overwrite may be from the listener for the user. Still sounds like an issue, but hopefully that unblocks you:

    export default compose(
        withStyles(styles),
        firestoreConnect(props => [
            {
                collection: "users",
                storeAs: "usersList"
            },
        ]),
        connect(mapStateToProps, mapDispatchToProps)
    )(ActiveUsersPanel);
...
const mapStateToProps = (state, props) => {
    return {
        users: state.firestore.data.usersList
    };
};
solveretur commented 3 years ago

unfortunately it's not working I even updated my project dependencies to

   "react-redux-firebase": "^3.7.0",
    "redux-firestore": "^0.13.0",

it still doesn't work. Also my migration python script using python firebase-admin library

def migrate_users(project_id, firebase_app, firestore_client):
    path = "/users"
    firestore_path = "users/{customer_id}"
    print(
        f"migrating from project: {project_id}, path: {path}"
    )
    ref = db.reference(path, firebase_app)
    document = ref.get() or {}
    items = document.items()
    size = len(items)
    for counter, item in enumerate(items):
        customer_id = item[0]
        notes = item[1]
        print(f"{counter+1}/{size} -- migrating customer_id: {customer_id}")
        current_document = firestore_client.document(
            firestore_path.format(
                partner_id=partner_id,
                customer_id=customer_id
            )
        )
        current_document.set(notes)
prescottprue commented 3 years ago

I'm not sure I understand the issue - are you saying accounts are not made in Firestore on login? Is this only for users that already existed or for new users as well? Could you provide a repo where the issue can be reproduced?

solveretur commented 3 years ago

Why is data under the userProfile path loaded incrementally and how to make it load all instantaneously ?

Zrzut ekranu 2020-09-14 o 17 47 08
prescottprue commented 3 years ago

It seems like you are using isLoaded(users) - you should be loading profile from state.firebase.profile

Still not sure I understand your original issue and there have been multiple question - are you able to provide an example where the issue can be reproduced?

solveretur commented 3 years ago

@prescottprue The original question is not relevant. My actual issue is that after I setup the userProfile path as users

export const reduxFirebase = {
    userProfile: "users",
    useFirestoreForProfile: true
};

When I want to fetch all of the documents under the path users, the library fetches them incrementally first returning my current logged-in user, then by dispatching DOCUMENT_ADDED actions it adds all of the rest of the profiles. Because of that my code returns undefined because I want to get avatarUrl of existing user who is not fetched yet though.

class ActiveUsersPanel extends React.Component {

    render(){
        const {firebase, classes, customersSessions, users, assignment} = this.props;
        const block = assignment && assignment.block;
        if (!isLoaded(users)) {
            return <CircularProgress mode="indeterminate"/>;
        }
       if (users){console.log(users);}
        ....
        const assignmentChip = assignment && assignment.uid && (
            // !!!!!! ---- assignment.uid IS UID OF PROFILE OF EXISTING USER
            // AND users[assignment.uid] IS SHOWN AS UNDEFINED ---- !!!!!!
            <Chip avatar={<Avatar src={users[assignment.uid].avatarUrl}/>}
                label={users[assignment.uid].displayName}
                onDelete={handleUnAssignment(this.props)}
            />
        );
        ....
        return (
            <Table>
                <TableBody>
                    <TableRow>
                        <TableCell>Assignment</TableCell>
                        <TableCell>
                            {assignmentChip}
                        </TableCell>
                    </TableRow>
                    ....
                </TableBody>
            </Table>
        );
    }
    ...
}

const mapStateToProps = (state, props) => {
    return {
        users: state.firestore.data.users,
        ...

    };
};

export default compose(
    withStyles(styles),
    firestoreConnect(props => [
        {
            collection: "users",
            storeAs: "users"
        }
        ...
    ]),
    connect(mapStateToProps, mapDispatchToProps)
)(ActiveUsersPanel);

In my previous comment I posted a screenshot of console outputs of the users value and how it is fetched. You can see that it's incrementally growing not fetched all in once How to make the library to fetch all of the documents from the users path in one moment not incrementally by dispatching DOCUMENT_ADDED action ? Is that more clear to you ?