React - why useContext returns undefined?
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
.
xxxxxxxxxx
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.
xxxxxxxxxx
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
.
xxxxxxxxxx
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;
Look at your case, simple steps:
- App.js imports
Login
from'./Components/Login'
- Login.js imports
AuthenticationContext
from'../App'
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.
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.