Reputation: 602
I have a React-Native project with redux. I perform some axios calls, and basically, the app works fine. But, there is one thing that is not right. I put a console.log before the dispatch, and even the app loads and renders everything just fine, I see the console.log looping on and on in the console. I'm not sure why this is happening, but I read the "run to completion" concept in Javascript, which can be the reason. Even though, I couldn't figure it out.
any ideas how can I fix this? thank you very much.
UPDATE: here is the component that invokes the action, in the renderEtiquetas() function. This can be the reason causing this loop, since it runs on every re-render cycle (not sure about this). I tried moving the invoke to componentDidMount() but it didn't seem to run.
I'm new to React so I'm probably doing something dumb.
component.js
class EtiquetasList extends Component {
componentDidMount() {
this.props.FetchEtiquetas();
}
renderEtiquetas() {
if ( this.props.etiquetas.length == 0 ) {
return <ActivityIndicator size="large" color="#00ff00" />
} else {
this.props.FetchGalleries( this.props.etiquetas );
if ( this.props.galleries.length > 0 ) {
return this.props.etiquetas.map(etiqueta =>
<EtiquetaDetail key={etiqueta.id} etiqueta={etiqueta} galleries={ this.props.galleries } />
);
}
}
}
render() {
return (
<ScrollView>
{ this.renderEtiquetas() }
</ScrollView>
);
}
}
const mapStateToProps = (state) => {
return {
etiquetas: state.data.etiquetas,
isMounted: state.data.isMounted,
galleries: state.slides.entries
};
};
export default connect(mapStateToProps, { FetchEtiquetas, FetchGalleries })(EtiquetasList);
actions.js
export function FetchGalleries( etiquetas ) {
return function (dispatch) {
return Promise.all(
etiquetas.map( record =>
axios.get('mydomain.com/?id='+record.id)
)).then(galleries => {
let my_data = [];
let data_json = '';
galleries.map( record => {
record.data.map( subrecord => {
// this is simplified for this example, it works as intended
data_json = data_json + '{ title: "' + subrecord.title+'"}';
});
my_data.push( data_json );
});
console.log( my_data ); // this keeps printing in the console
return dispatch({ type: FETCH_GALLERIES_SUCCESS, payload: my_data });
});
}
}
Upvotes: 4
Views: 961
Reputation: 651
You are close, you just need to return or await Promise.all otherwise it will not be awaited
export function FetchGalleries( etiquetas ) {
return function (dispatch) {
return Promise.all(....
}
// UPDATE: The answer from 李骏骁 is correct
Upvotes: 1
Reputation: 581
Aha, FetchGalleries
is running inside the render function, it will cause an action->render->action->render
infinite loop.
Edit:
How about trying to merge your FetchGalleries
and FetchEtiquetas
into one action:
export const fetchGalleries = () => {
return function (dispatch) {
return axios.get('/path/to/etiquetas').then(etiquetas => {
dispatch({ type: FETCH_ETIQUETAS_SUCCESS, payload: etiquetas });
// ... your previous promise all code
});
}
}
and only need to call this new fetchGalleries
at componentDidMount
.
Upvotes: 3