0

I have a userContext that is authenticating the user. It is working, but after successful login I want the user to be directed to the /dashboard. so I'm using this.props.history.push('/dashboard'); but I'm getting the below error.

TypeError: Cannot read property 'props' of undefined

Is there a better way to do this? While using a function?

UserContext.js

import React, {useState, createContext, useEffect} from 'react'
import Firebase from 'firebase'
import { Redirect } from 'react-router'

export const UserContext = createContext();


export const UserProvider = props => {
  const [user, setUser] = useState({
    username: "blank",
    loggendIn: false
  });


  var id = localStorage.getItem('id');
  // check if its null
  console.log(id);
  useEffect(() => {
    if (id != null) {
      console.log('id is there');
      // load user from realtime database
      const dbOBJ = Firebase.database().ref().child("users").child(id);
      dbOBJ.on('value', function(snapshot) {
        setUser(snapshot.val());
      });

    } else {
      console.log('no id :( ');
    }
    console.log(props.history);
    this.props.history.push('/dashboard');
  }, [id]);

  return (
    <UserContext.Provider value = {[user, setUser]} >
    {  props.children}
    </UserContext.Provider>
  );
}

app.js

import React from 'react';
import NavBar from './components/navBar';
import Login from './components/login';
import Session from './components/session';
import Dashboard from './components/dashboard';
import './App.css';
import Container from '@material-ui/core/Container';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';

import { UserProvider } from './model/UserContext'


function App() {

  return (
    <div>
      <UserProvider>
      <Session />
       <NavBar />
        <Container maxWidth="sm">
         <Router>
         <Route path='/Login' component={Login}  />
         <Route path='/Dashboard' component={Dashboard}  />
         </Router>
       </Container>
      </UserProvider>
    </div>
  );
}

export default App;
4
  • Where does the history prop come from? It is usually injected via the withRouter HOC from react-router. Commented Sep 27, 2019 at 5:15
  • Do you use 'withRouter' like this? export const UserProvider = props => withRouter({ Commented Sep 27, 2019 at 5:21
  • no... more like const UserProvider = withRouter((props => {...}); but to be honest it is easier to write your functional component normally, then wrap the export, like export default withRouter(UserProvider); Commented Sep 27, 2019 at 5:24
  • this think this is the way to do it, but Im getting an error Attempted import error: 'UserProvider' is not exported from './model/UserContext'. Bit i am exporting the function const UserProvider = props => { ... } export default withRouter(UserProvider); Commented Sep 27, 2019 at 5:33

2 Answers 2

1

That is a functional component, there is no instance for this to exist on, history would just be on props. You also probably need to "inject" the router's history object into props as well.

import React, {useState, createContext, useEffect} from 'react'
import Firebase from 'firebase'
import { Redirect, withRouter } from 'react-router'

export const UserContext = createContext();


const UserProvider = ({  // don't export here
  children, // destructuring props here so it is clearer
  history
}) => {
  const [user, setUser] = useState({
    username: "blank",
    loggendIn: false
  });


  var id = localStorage.getItem('id');
  // check if its null
  console.log(id);
  useEffect(() => {
    if (id != null) {
      console.log('id is there');
      // load user from realtime database
      const dbOBJ = Firebase.database().ref().child("users").child(id);
      dbOBJ.on('value', function(snapshot) {
        setUser(snapshot.val());
      });
    } else {
      console.log('no id :( ');
    }
    console.log(props.history);
    history.push('/dashboard'); // <-- no this.props, just props or destructured props
  }, [id]);

  return (
    <UserContext.Provider value = {[user, setUser]} >
    { children }
    </UserContext.Provider>
  );
}

export default withRouter(UserProvider);
Sign up to request clarification or add additional context in comments.

7 Comments

thanks for getting back to me so quickly, the issue when I do that is. its saying "TypeError: Cannot read property 'push' of undefined". Do i need to push props in the app.js? I'll add the code to the post.
Updated to show using the router's withRouter HOC.
I think this is the way to do it, but Im getting an error Attempted import error: 'UserProvider' is not exported from './model/UserContext'. But i am exporting the function const UserProvider = props => { ... } export default withRouter(UserProvider); do I need to add somthing to the app.js?
Ah, I see, try either removing the default part from the export, or try removing the {} on the import. The issue is if you do a default export then the import would simple be import UserProvider from './model/UserContext';, or if you want to keep it a named export you'd have to do the export const UserProvider = withRouter(props => ...
Yes, that fixed it :) but getting another error lol, ```Error: "Invariant failed: You should not use <withRouter(UserProvider) /> outside a <Router>"`` I moved <Router> to the top of the list in the return() of the App function in the app.js file. But still getting the same issue.
|
0

I think you're mixing up multiple thing:

Fat arrow functions don't have a this on it defined it'll pick up window as this for your code.

window.name = 'Mamba';
(() => {console.log(this.name)})();

So you need to use the props directly here like this:

this.props.history.push('/dashboard'); => props.history.push('/dashboard');

You might like to go through this question if you're still unsuccessful

1 Comment

I think your right, but I'm getting "history.push" us missing. Do I need to add this to the app.js? Is props.history.push( )built into react? or should I use something else to redirect?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.