initial file

import React, { Component } from "react"; import {connect} from "react-redux"; import List from "../../components/List"; import { getData } from "../../store/actions/getData"; import Spinner from "../../UI/Spinner/Spinner"; class ProductsArea extends Component { componentDidMount() { this.props.onGetProducts(); } render() { if (this.props.products.length === 0) { return <Spinner />; } return <List isProducts = {this.props.products}/>; } } const mapStateToProps = (state) => { return { products: state.prod } }; const dispatchStateToProps = (dispatch) => { return { onGetProducts: () => getData(dispatch) } }; export default connect(mapStateToProps, dispatchStateToProps)(ProductsArea); //метод getData export function getData(dispatch) { dispatch({ type: actions.PRODUCTS_LOADING}); axios.get("api/getData") .then(res => { dispatch({ type: actions.GET_PROD_LIST, val: res.data }); }); } 

// List - here the Render method runs an infinite number of times, data successfully arrives

 import React, {Component} from "react"; import Spinner from "../UI/Spinner/Spinner"; class List extends Component { state = { dataLoaded: false }; dataLoadHandler = () => { this.setState({ dataLoaded: true }); }; render() { let result = <Spinner/>; const products = this.props.isProducts; console.log(products); if (products.length > 0) { this.dataLoadHandler(); } if (this.state.dataLoaded) { result = products.map(prod => { const primaryImgUrl = `img/product/mediam/${prod.PrimaryImg}`; const secondaryImgUrl = `img/product/mediam/${prod.SecondaryImg}`; const isNew = prod.New ? (<div className="label_new"> <span className="new">new</span> </div>) : null; const isSalePercent = prod.SalePercent != null ? (<div className="sale-off"> <span className="sale-percent">-55%</span> </div>) : null; return (<div className="single-product"> <div className="col-md-3 col-sm-4 col-xs-12"> {isNew} {isSalePercent} <div className="product-img"> <a href="#"> <img className="primary-img" src={primaryImgUrl} alt="Product" /> <img className="secondary-img" src={secondaryImgUrl} alt="Product" /> </a> </div> </div> <div className="col-md-9 col-sm-8 col-xs-12"> <div className="product-description"> <h5><a href="#">{prod.Name}</a></h5> <div className="price-box"> <span className="price">$ {prod.Price}</span> <span className="old-price">$ {prod.OldPrice}</span> </div> <p className="description">{prod.Description}</p> <div className="product-action"> <div className="button-group"> <div className="product-button"> <button><i className="fa fa-shopping-cart"></i> Add to Cart</button> </div> <div className="product-button-2"> <a onClick={this.openModalHandler} href="#" className="modal-view" id={ prod.ProductId} data-toggle="modal" data-target="#productModal" title="Quickview"><i className="fa fa-search-plus"></i></a> </div> </div> </div> </div> </div> </div>); }); } return ( <div className="listview"> {result} </div> ); } 

}

export default list;

Why does this situation arise, who can explain?

    1 answer 1

    Try not to do setState inside render

    You have 2 identical conditions: products.length > 0 and this.state.dataLoaded

    When you have no products: products.length > 0 === false and this.state.dataLoaded === false

    When there are products: products.length > 0 === true and this.state.dataLoaded === true

    It turns out that when you get the list of products, the dataLoadHandler function is dataLoadHandler inside it you have setState , which causes the component to be redrawn. So you endlessly redraw.

    Generally meaning in the design

     if (products.length > 0) { this.dataLoadHandler(); } 

    for your component no.

    Rewrite your condition

     if (products.length > 0) { result = products.map(prod => { // тут ваш код скопируйте ... } } 

    Then everything will be fine.

    UPD: you can simply change the terms of this.state.dataLoaded and products.length > 0 places, this will also work.

    • Thanks for the explanation. Everything works) - Sergey Chizhik
    • @ Sergey Chizhik mark the answer as a solution, please :) - Ilya Paymushkin