Meteor.userId() not reactive in a react component?

Viewed 179

I just implemented a small authentification system to my current project using the accounts-password package. The authentification itself is working properly.

In my view, there are some buttons and stuff which should be only displayed to logged in users. I got this working by checking Meteor.userId(). If null, the buttons won't be displayed.

The problem is the following: When I'm logging in (or out), my view doesn't rerender. It's simply not hiding or showing the buttons which shall be toggled. It always takes an independent rerender to show or hide them.

The Meteor-Documentation states, that Meteor.userId() shall be reactive but it's not behaving that way in my component.

Here's some react-component showing how my view looks like showing or hiding buttons depending on Meteor.userId():

class SomeReactComponent extends React.Component {
    constructor(props) {
        super(props);
        ...
    }

    ...

    render() {
        return (
            <span>
                <p>Text that should be displayed to anyone!</p>
                { Meteor.userId() ? (
                    <button id="btn">
                        This button is only available to logged in users
                    </button>
                ) : ""}
            </span>
        );
    }
}
3 Answers

Use createContainer, this will make your Meteor.userId() reactive. to install just type:

meteor npm install --save react-addons-pure-render-mixin

meteor add react-meteor-data

import React from "react";
import {createContainer} from "meteor/react-meteor-data";

class SomeReactComponent extends React.Component {
    constructor(props) {
        super(props);
        
    }

   

    render() {
        return (
            <span>
                <p>Text that should be displayed to anyone!</p>
                { this.props.authenticated ? (
                    <button id="btn">
                        This button is only available to logged in users
                    </button>
                ) : ""}
            </span>
        );
    }
}
export default createContainer(()=>{
  return {
    authenticated: Meteor.userId(),
  }
},SomeReactComponent);

Another answer worth looking in to is the trackerReact package at https://github.com/ultimatejs/tracker-react

Using this should make the component be reactive, just as you'd expect it to be.

class SomeReactComponent extends TrackerReact(React.Component) {

Actually, there is an easy way to do that:

  1. Add import {useTracker} from "meteor/react-meteor-data";
  2. const user = useTracker(() => { return Meteor.userId() });

Full Example :

import {useTracker} from "meteor/react-meteor-data";

    export default function App() {
        const user = useTracker(() => {
            return Meteor.userId()
        });
        if (!user) {
            return (
                    <Global_Router Client={null} About={About} HomeNavbar={HomePageNav} HomePage_Home={HomePage_Home}
                                   HomeFooter={Footer} Homepage_Contacts={Homepage_Contacts}/>
            );
        }
        else {
            return(
                <RouterClient/>
    
            );
        }
Related