0

i'm facing a small problem with my react app. I'm using bluprintjs Toaster, and i need to display them on top of all other component, no matter what. Like this if there is an error during login or logout the user will always see the toast even if there is a redirection.

My problem is, that i have a middle component that is used to protect access to unAuthenticated user.

On my app class i have a ref to the Toaster and can easily call renderToaster to display a toast. So the method is working correctly.

But when i pass it to my ProtectedRoute and then to MyForm Component i can't call it in the MyFrom component. From App -> ProtectedRoute -> MyForm if i print this.props i can see the renderToaster() Method, but i think the link from MyFrom -> ProtectedRoute -> App is somehow broken because on MyFrom i have the this.toaster is undefined error.

How can i call my parent parent method. Or how can i create a link between app and MyForm compenent passing through ProtectedRoute?

Thank you for your help.

My App class:

 class App extends Component {

  renderToaster(intent, message) {
    this.toaster.show({
        intent: intent,
        message: message
    });
  }

  <React.Fragment>
    <NavBarComponent />
        <Switch>
            <ProtectedRoute
                exact
                path="/path1"
                name="path1"
                location="/path1"
                renderToaster={this.renderToaster}
                component={MyForm}
            />
            <ProtectedRoute
                exact
                path="/path2"
                name="path2"
                location="/path2"
                component={params => <MyForm {...params} renderToaster={this.renderToaster} />}
            />
        </Switch>
        <Toaster
            position={Position.BOTTOM}
            ref={element => {
                this.toaster = element;
            }}
        />
  </React.Fragment>
}

My ProtectedRoute class:

import React, { Component } from 'react';
import { Route, Redirect } from 'react-router-dom';
import { AuthContext } from '../providers/AuthProvider';

class ProtectedRoute extends Component {
    state = {};

    render() {
        const { component, ...rest } = this.props;
        const Component = component;

        return (
            <AuthContext>
                {({ user }) => {
                    return user ? (
                        <Route render={params => <Component {...params} {...rest} />} />
                ) : (
                        <Redirect to="/" />
                    );
                }}
            </AuthContext>
    );
   }
}

export default ProtectedRoute;

And on my last class (MyForm passed to the protected Route) i call my renderToaster Method like this:

/**
 * Component did Mount
 */
componentDidMount() {
    this.props.renderToaster(Intent.PRIMARY, 'helloo');
}
1020rpz
  • 914
  • 10
  • 21
  • Possible duplicate of [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – Estus Flask Feb 17 '19 at 00:09

1 Answers1

1

You either need to bind renderToaster in the class constructor:

constructor(){
    this.renderToaser = this.renderToaster.bind(this);
}

or declare renderToaser as an ES7 class property.

renderToaster = (intent, message) => {
    this.toaster.show({
        intent: intent,
        message: message
    });
}

The problem is this in renderToaster isn't pointing where you think it is when the method is passed to the child component. If you use either of these methods, then this will refer back to the class.

See the official docs for more detail: https://reactjs.org/docs/handling-events.html

Frank Riccobono
  • 1,043
  • 6
  • 13
  • Thanks, it was just that. Sometime i'm to deep into it to just see those simple things. But anyway thanks your for your time. – 1020rpz Feb 17 '19 at 16:30