0

I'm trying to build React app that shows a ProfilePage component only if user Logged in. Ive Application component(wrapped in Provider component called UserProvider) which renders either ProfilePage or Route to either Signin or signup pages depending on if user exists. I'm able to use useContext in Application component. But it says user undefined when I try to use useContext in ProfilePage (the console.log in ProfilePage is displaying User in profile undefined). Here i'm also using Firebase Authentication for signing-in and signing-up users. Is there a way I can use user data using useContext in ProfilePage? Below are the components I have.

UserProvider.js

import React, { Component, createContext } from 'react';
import { auth } from '../firebase';

export const UserContext = createContext({ user: null });

class UserProvider extends Component {
  state = {
    user: null,
  };

  componentDidMount = () => {
    auth.onAuthStateChanged((userAuth) => {
      console.log('userAuth', userAuth);
      this.setState({ user: userAuth });
    });
  };
  render() {
    return (
      <UserContext.Provider value={this.state.user}>
        {this.props.children}
      </UserContext.Provider>
    );
  }
}
export default UserProvider;

App.js

import React from 'react';
import UserProvider from './providers/UserProvider';
import Application from './components/Application';

function App() {
  return (
    <UserProvider>
      <Application />
    </UserProvider>
  );
}

export default App;

Application.js

import React, { useContext } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import ProfilePage from './ProfilePage';
import SignUp from './SignUp';
import Login from './Login';
import { UserContext } from '../providers/UserProvider';

const Application = () => {
  const user = useContext(UserContext);
  console.log('user in application', user);
  return user ? (
    <ProfilePage />
  ) : (
    <Router>
      <Route path="/signup">
        <SignUp />
      </Route>
      <Route exact path="/">
        <Login />
      </Route>
    </Router>
  );
};
export default Application;

ProfilePage

import React, { useContext } from 'react';
import UserContext from '../providers/UserProvider';
import { auth } from '../firebase';

import { useHistory } from 'react-router-dom';

const ProfilePage = () => {
const history = useHistory();
  const signOut = () => {
    auth.signOut();
    history.push('/');
  };
  const user = useContext(UserContext);
  console.log(' user in profile', user); //displaying 'user in profile undefined'
  const { email } = user;
  return (
    <div>
      Profile
      <div>
        <h3>{email}</h3>
      </div>
      <button
        onClick={() => {
          signOut();
        }}
      >
        Sign out
      </button>
    </div>
  );
};
export default ProfilePage;

Login.js

import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { auth } from '../firebase';

const Login = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState(null);

  const onChangeHandler = (e) => {
    const { name, value } = e.currentTarget;

    if (name === 'userEmail') setEmail(value);
    else if (name === 'userPassword') setPassword(value);
  };
  console.log('email', email, 'password', password);
  const signInWithEmailAndPasswordHandler = (event, email, password) => {
    event.preventDefault();
    auth.signInWithEmailAndPassword(email, password).catch((error) => {
      setError('Error signing in with password and email!');
      console.error('Error signing in with password and email', error);
    });
  };

  return (
    <div>
      <h1>Sign In</h1>
      <div>
        {error !== null && <div>{error}</div>}
        <form>
          <label htmlFor="userEmail">Email:</label>
          <input
            type="email"
            name="userEmail"
            value={email}
            placeholder="E.g: abc@gmail.com"
            id="userEmail"
            onChange={(event) => onChangeHandler(event)}
          />
          <label htmlFor="userPassword">Password:</label>
          <input
            type="password"
            name="userPassword"
            value={password}
            placeholder="Enter Password"
            id="userPassword"
            onChange={(event) => onChangeHandler(event)}
          />
          <button
            onClick={(event) => {
              signInWithEmailAndPasswordHandler(event, email, password);
            }}
          >
            Sign in
          </button>
        </form>

        <p>
          Don't have an account? <Link to="signUp">Sign up here</Link> <br />{' '}
        </p>
      </div>
    </div>
  );
};
export default Login;
charishma
  • 3
  • 4
  • Is `App` and `ProfilePage` in same directory? – T J May 07 '21 at 21:48
  • @TJ No, they are in different directories. And I figured I missed { } around UserContext in an import statement in ProfilePage component. Code worked just fine after fixing that. – charishma May 09 '21 at 07:03

0 Answers0