I've played around with the code for a while now. I'm grabbing data from Firebase and populating a list of objects from that data onto this UserProfile page. I just want it to work so that when I go on the profile page, a list of their items is listed there.
The problem is that with this version of the code I have to click on the profile link twice for the items to show up, but the display name shows up fine. I know setState is asynchronous. I've tried setting the state in a callback in setState. I've tried checking if the snapshot exists beforehand. I've tried componentDidMount and componentDidUpdate. None of these things have helped, I just end up with this.state.items.map can't be called or newState is some empty, weird thing. I don't know where I'm going wrong now.
When I console debug this, it looks like setState is being called when nothing has been fetched from Firebase so far and never gets called later.
Maybe something is wrong with how I set newState because when I console log newState is empty when I'm trying to first set it. I just don't know when to set this at the appropriate time for the first render.
class UserProfile extends Component {
constructor(props){
super(props)
this.state = {
redirect: false,
userId: this.props.match.params.id,
displayName: "",
items: []
}
this.userRef = firebaseDB.database().ref(`/Users/${this.state.userId}`)
this.usersItemsRef = firebaseDB.database().ref(`/Users/${this.state.userId}/items`)
}
componentWillMount() {
this.userRef.on('value', snapshot => {
this.setState({
displayName: snapshot.val().displayName
});
});
this.usersItemsRef.on('value', snapshot => {
let usersItems = snapshot.val();
let newState = [];
for (let userItem in usersItems) {
var itemRef = firebaseDB.database().ref(`/items/${userItem}`)
itemRef.once('value', snapshot => {
var item = snapshot.val()
newState.push({
id: itemRef.key,
title: item.title
});
})
}
this.setState({
items: newState
})
});
}
componentWillUnmount() {
this.userRef.off();
this.usersItemsRef.off();
}
render() {
return (
<div style={{marginTop: "100px"}}>
<h1>{this.state.displayName}</h1>
<Link className="pt-button" aria-label="Log Out" to={"/submit_item/"+this.state.userId} >Submit an item</Link>
<section className='display-itemss'>
<div className="wrapper">
<ul>
{this.state.items.map((item) => {
return (
<li key={item.id}>
<h3>{item.title}</h3>
</li>
)
})}
</ul>
</div>
</section>
</div>
);
}
}