7

I'm new to React Router and trying to do a redirect from inside a provider using the new Conext API. basically my provider looks like this.

/* AuthContext.js */

class AuthProvider extends React.Component {

  state = { isLoggedIn: false }

  constructor() {
    super()
    this.login = this.login.bind(this)
    this.logout = this.logout.bind(this)
  }

  login() {

    this.setState({ isLoggedIn: true })

    // Need to redirect to Dashboard Here

  }

  logout() {
    this.setState({ isLoggedIn: false })
  }

  render() {
    return (
      <AuthContext.Provider
        value={{
          isLoggedIn: this.state.isLoggedIn,
          login: this.login,
          logout: this.logout
        }}
      >
        {this.props.children}
      </AuthContext.Provider>
    )
  }
}

const AuthConsumer = AuthContext.Consumer

export { AuthProvider, AuthConsumer }

I've read a lot about how to pass the history object using props and how to use a component but I can't see how these approaches would work here. My context provider sits at the top of the tree so it's not a child of the Router so I can't pass props. It's also not a standard component so I can't just insert a component, unless I've misunderstood something (which is very possible).

Edit: Looks like the way to go is withRouter, but how to export my AuthProvider in the code above so that history.push is available in my login function? As you can see I'm exporting multiple components wrapped in {} so can you wrap one of these in a HOC and do you have to explicitly pass history in or is it always available inside the component that's being wrapped?

jonhobbs
  • 21,469
  • 23
  • 94
  • 144
  • did u try using history -> this.props.history.push("/dashboard"); – Srinivas Jul 23 '18 at 11:45
  • AuthProvider doesn't have props.history, unless you know a way I can add the Router history object to the props? – jonhobbs Jul 23 '18 at 11:47
  • use withRouter, sth like this to get access of history. const AuthButton = withRouter( ({ history }) =>history.push("/")); – Srinivas Jul 23 '18 at 11:48
  • Ah, OK, just read the withRouter docs and it says it gives access to "the history object's properties and the closest 's match", so it looks like that will work for my use case, but I'm guessing because it's a grandparent of the 's that it won't get anything in the 'match' property. I'll read into it a bit further. If you add that as an answer I'll mark it as correct. many thanks. – jonhobbs Jul 23 '18 at 11:58

1 Answers1

2

use withRouter, sth like this to get access of history.

 const AuthButton = withRouter( ({ history }) =>history.push("/"));

Try This:

    import { Route } from "react-router-dom";

  class AuthProvider extends React.Component {
    yourFunction = () => {
      doSomeAsyncAction(() =>
        this.props.history.push('/dashboard')
      )
    }

    render() {
      return (
        <div>
          <Form onSubmit={ this.yourFunction } />
        </div>
      )
    }
  }

  export default withRouter(AuthProvider);

Best explanation can be found here: Programmatically navigate using react router

Srinivas
  • 1,378
  • 3
  • 16
  • 27
  • Just checking before I mark as correct, how I export my AuthProvider wrapped in withProvider so I can use history inside of it. I'm about to edit my question to reflect that. – jonhobbs Jul 23 '18 at 12:25
  • No, when trying to use withRouter with my AuthProvider I get the error - "You should not use or withRouter() outside a " – jonhobbs Jul 23 '18 at 13:45
  • OK, it worked when I swapped the nesting of the AuthProvider and BrowserRouter tags so that the AuthProvider was inside the BrowserRouter. – jonhobbs Jul 23 '18 at 14:14
  • OK, I've marked your answer as correct because it led me to the correct answer, but in my application tthe whole point of using a context provider was that my form which contains the call to the login function can't be in the provider itself, it's way down in the the component tree inside the context consumer. The hard bit was getting access to the router from within the provider which I now can thanks to withRouter and nesting the provider inside the router component. – jonhobbs Jul 23 '18 at 14:16