Reputation: 9285
I am trying to understand higher-order-components(referred to as HOC below):
As such, I have created a sample HOC to do GET requests for my component:
import React from 'react';
import { Text } from 'react-native';
import axios from 'axios';
export default (Elem, props = {}) => {
// mock props for testing
props = {
apiRequests: {
"todoList": {
url: "https://jsonplaceholder.typicode.com/todos"
}
}
}
return class extends React.Component {
componentWillMount() {
let apis = Object.keys(props.apiRequests);
for(let i = 0; i < apis.length; i++) {
props.apiRequests[apis[i]].done = false
axios.get(props.apiRequests[apis[i]].url).then((resp) => {
console.warn("done")
props.apiRequests[apis[i]].done = true
props.apiRequests[apis[i]].data = resp.data
})
}
}
render() {
return (<Elem {...props} />)
}
}
}
Now, when I wrap my component with the above HOC, I get the props with done
as false
.
However, soon, when I get my API response, the HOC logs done
in my console, but the data in my component isn't updated. What am I doing wrong?
Upvotes: 1
Views: 2017
Reputation: 222369
Props are immutable. This
props.apiRequests[apis[i]].done = true
is a mistake and won't cause child component to be re-rendered.
A state that is received from asynchronous request should be stored in component state, setState
triggers a re-render. componentWillMount
was deprecated because it was misused for asynchronous routines. It should be:
return class extends React.Component {
this.state = {};
componentDidMount() {
let apis = Object.keys(props.apiRequests);
for(let i = 0; i < apis.length; i++) {
axios.get(props.apiRequests[apis[i]].url).then((resp) => {
this.setState({ apis[i]]: resp.data });
})
}
}
render() {
return (<Elem data={this.state} />)
}
}
Depending on how data is expected to be received, state updates could be performed in batch with Promise.all
.
Upvotes: 1