Reputation:
I have the following code, in App.js;
constructor() {
super();
this.state = {
isLoggedIn: false,
username: "",
}
}
componentDidMount() {
let isLoggedIn = false;
let username = "";
if (localStorage.getItem("token")) {
fetch("https://localhost:8000/user", {
method: "POST",
headers: {
"Authorization": `Bearer ${localStorage.getItem("token")}`
}
}).then(response => response.json()).then(response => {
if (response.success) {
isLoggedIn = true;
username = response.username;
} else {
isLoggedIn = false;
username = "";
localStorage.removeItem("token");
}
this.setState({
isLoggedIn : isLoggedIn,
username: username
})
})
}
}
render() {
return (
<Navbar username={this.state.username}/>
)
}
By console logging the output, once componentDidMount is called the username in state is assigned as it should be. In Navbar.js;
constructor(props) {
super(props);
this.state = {
navComponents: []
}
}
componentDidMount() {
console.log(this.props.username);
let navComponents = [];
if (this.props.username === "") { //Not Signed In.
navComponents.push(
<ul className="Navbar-list">
<li className="Navbar-item">
<Link to="/register" className="Navbar-link">Sign Up</Link>
</li>
<li className="Navbar-item">
<Link to="/login" className="Navbar-link">Log In</Link>
</li>
</ul>
);
} else {
navComponents.push(
<p>Hello, {this.props.username}</p>
)
navComponents.push(
<ul className="Navbar-item">
<Link to="/signout" className="Navbar-link">Sign Out</Link>
</ul>
)
}
this.setState({
navComponents : navComponents
})
}
I believe it should be getting username from App. However, username is always an empty string(The initial state of App). I'm unsure as to why Navbar isn't updating once component is mounted in App.
Upvotes: 0
Views: 32
Reputation: 1322
Your doing it wrong, isn't ur render function suppose to do the markup for a component, try like this should work fine.
constructor(props) {
super(props);
}
render(){
return (
{this.props.username ?
<>
<p>Hello, {this.props.username}</p>
<ul className="Navbar-item">
<Link to="/signout" className="Navbar-link">Sign Out</Link>
</ul>
</>
:
<ul className="Navbar-list">
<li className="Navbar-item">
<Link to="/register" className="Navbar-link">Sign Up</Link>
</li>
<li className="Navbar-item">
<Link to="/login" className="Navbar-link">Log In</Link>
</li>
</ul>})
}
Upvotes: 1
Reputation: 12874
The reason is very simple, because componentDidMount
of Navbar
only being fired once, before username
has a value.
What's happening with the flow is as below
App.js
render
being invokedApp.js
componentDidMount
being invokedApp.js
fire API callNavbar
render
being invokedNavbar
componentDidMount
being invokedNow because componentDidMount
of Navbar
will only be fired once, hence you will always see this.props.username
is empty there. One of the simplest solution is by to handle your logic at componentDidUpdate
instead of componentDidMount
Upvotes: 0