Reputation: 4588
I´m trying to use promise to fill a react component. I have debugged and the statement this.setState({items: items})
inside componentWillMount()
is called after render()
so always the items array in the render function is empty. Also I have tried to use componentDidMount()
.
Which would it be the right approach?
interface Props extends React.Props<ItemsListComponent> {
isAddButtonClicked : boolean;
newItem : string;
}
interface State {
items : Array<ItemEntity>;
}
export class ItemsListComponent extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {items: []};
}
public componentWillMount() {
itemAPI.getAllItems().then((items) => {
this.setState({items: items})
});
}
render() {
return(
<div className="container">
<div className="row">
<ul className="list-group">
{this.state.items.map((item : ItemEntity) =>
// Each child in an array or iterator should have a unique "key" prop. React doc.
<li className="list-group-item" key={item.id}>{item.task}</li>
)}
</ul>
</div>
</div>
);
}
}
Upvotes: 0
Views: 2756
Reputation: 4532
According to the React Documentation calling APIs is best done in componentDidMount().
That in combination with the answer from Benjamin will give you the best implementation.
Upvotes: 0
Reputation: 276286
The problem is that the data is not yet available when React renders the component. In practice, your code should guard against this, either at the component or above:
render() {
if(!this.state.items) return null; // or loading indicator, data has not returned yet
return (<div className="container">
...
</div>);
}
Upvotes: 3
Reputation: 2339
From the docs: componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state synchronously in this method will not trigger a re-rendering. Avoid introducing any side-effects or subscriptions in this method.
You should be able to make your request in componentDidMount(). This ensures a rerender when the state changes. If it's still empty, there's a chance that your map in your render is returning an empty array. Make sure you are properly formatting the item that is returned from your api. There's a chance the response is of the form { items: [] }.
Upvotes: 0
Reputation: 411
Create method 'asyncUpdate(data) { this.setState(data) }' in constructor set 'this.asyncUpdate = this.asyncUpdate.bind(this)'
And after your promise call trigger 'this.asyncUpdate(promisedData)'
Should help
Upvotes: 0
Reputation: 1343
I would put the itemAPI.getAllItems()
in component's constructor. Once the items arrive, no matter when, the state will be updated and this will trigger render()
.
Upvotes: 0