Languages

React - why useContext returns undefined?

0 points
Asked by:
Hayley-Mooney
377

Take a look at these three components. Can some explain why Login component can't see the loginUser method from the authenticationService?

Everything seems right: passing context, imports and yet it returns undefined.

1. App component - in which I created AuthenticationContext and passed it to the Container using Provider.

import React, { useState, createContext } from 'react';
import Login from './Components/Login';
import Container from './Components/Container';

export const AuthenticationContext = createContext();

const App = () => {
  // ...
  const authenticationService = {
    loginUser: (user) => {
      setUser(user);
      return true;
    },
    // ...
  };
  return (
    <div>
      <AuthenticationContext.Provider value={authenticationService}>
        // ...
        <Container />
      </AuthenticationContext.Provider>
    </div>
  );
};

export default App;

2. Container component - in which I render Login component.

import React from 'react';
import Login from './Login';

const Container = () => {
  return (
    <div className="container" style={containerStyle}>
      <Login />
    </div>
  );
};

export default Container;

3. Login component - here I want to use loginUser from App's authenticationService but it's undefined.

import React from 'react';
import { AuthenticationContext } from '../App';

// ...

const Login = () => {
  const authenticationService = React.useContext(AuthenticationContext);

  // ...

  const handleLogin = () => {
    if ((usernameRef.current.value = 'root123215' && passwordRef.current.value === 'root123215')) {
      authenticationService.loginUser('root');
      console.log('successful login');
    } else {
      console.log('login failed');
    }
  };

  return (
    <form onSubmit={handleLogin} style={loginStyle}>
      <div>
        <label>Username: </label>
        <input type="text" ref={usernameRef} />
      </div>
      <div>
        <label>Password: </label>
        <input type="password" ref={passwordRef} />
      </div>
      <button type="submit">Login</button>
    </form>
  );
};

export default Login;
2 answers
7 points
Answered by:
Hayley-Mooney
377

Look at your case, simple steps:

  1. App.js imports Login from './Components/Login'
  2. Login.js imports AuthenticationContext from '../App'
  3. AuthenticationContext is created in App.js with:
    export const AuthenticationContext = createContext();
    // AuthenticationContext doesn't exist in step 2 yet

Summary:

App imports Login and inside Login App is imported again - keep contexts in separated files.

0 comments Add comment
0 points
Answered by:
Hayley-Mooney
377

Quick solution:

  • put context into a separate file

Sometimes importing a lot of files creates a cycle that leads to errors.

When I put context from the App into a separate file - contexts.js (which is a good practice) it worked.

0 comments Add comment
Native Advertising
🚀
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

❤️💻 🙂

Join