Reputation: 531
I have a simple React App. I defined several routes and one of them is Login. After user logs in successfully in Login component, I want to display his username in the top menu. I'm using localStorage to store the value and I expected that it would get updated automatically when the value changes. However, I need to refresh the page to see the change. What am I missing?
This is the code of the main App component:
import React, { Component } from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Redirect
} from 'react-router-dom';
import Login from './Login.js'
import Register from './Register.js'
import About from './About.js'
class App extends Component {
render() {
return (
<Router>
<div className="topMenu">
<Link to="/">Login</Link>
<span> </span>
<Link to="/register">Register</Link>
<span> </span>
<Link to="/about">About</Link>
<span> </span>
<span>Logged in user: {localStorage.getItem("username")}</span>
</div>
<div className="container">
<Route exact path="/" component={Login}/>
<Route path="/register" component={Register}/>
<Route path="/about" component={About}/>
</div>
</Router>
);
}
}
export default App;
In Login component in login() method I'm simply adding username to localStorage:
localStorage.setItem("username", username);
Shouldn't it be enough to update the displayed value in App component?
Upvotes: 1
Views: 1382
Reputation: 1914
One way of doing this can be storing the name of the user in the state of app component and create a function in app component which updates the username in the state and pass that function as a callback to the login component. When the login is successfull, the login page will call this function and update the username in app component. Since the state is changed, the app component will be rendered again with new state (updated username).
import React, { Component } from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Redirect
} from 'react-router-dom';
import Login from './Login.js'
import Register from './Register.js'
import About from './About.js'
class App extends Component {
state = { username: "" };
updateUsername = () => {
const username = localStorage.getItem("username");
this.setState({ username: username });
};
render() {
return (
<Router>
<div className="topMenu">
<Link to="/">Login</Link>
<span> </span>
<Link to="/register">Register</Link>
<span> </span>
<Link to="/about">About</Link>
<span> </span>
<span>Logged in user: {localStorage.getItem("username")}</span>
</div>
<div className="container">
<Route
path="/login"
render={props => <Login {...props} updateUsername={updateUsername} />}
/>
<Route path="/register" component={Register}/>
<Route path="/about" component={About}/>
</div>
</Router>
);
}
}
export default App;
Now the updateUsername
function should be available in Login component via this.props.updateUsername
. You can call this function when the login is successfull to update state in app component.
Upvotes: 2
Reputation: 2158
You can use Context API, and store all the data from local storage also in the state of application so whenever you update local storage make sure to update and state of the application and React will detect changes in the state of the app and will trigger render
lifecycle.
See here documentation on how to use Context API
it's very simple to implement, also working with localstorage
you can use this package ngx-webstorage
more inforation you can find here https://www.npmjs.com/package/ngx-webstorage
Upvotes: 2
Reputation: 495
React re-renders when the values in state or props change. You need to store the value which you get from the localStorage to the state in App component.
Since this starts to look like an app which needs to share data between many components which may not necessarily be in a parent-child relationship, using Redux may be a good idea.
Upvotes: 1