Странное поведение цикла в js (react)

94
25 ноября 2021, 16:10

Есть такой класс. Его предназначение - рендер каталога товаров, которые он получает из API через fetch().

    export class Store extends Component {
    constructor(props) {
        super(props);
        this.state = { isFetched: false, data: [] }
    }
    componentDidMount() {
        this.fetchData();
    }
    fetchData() {
        fetch('api/store/getstoredata').then(response => response.json()).then(result => this.setState({ data: result, isFetched: true }));
    }
    buildGood(x) {
        if (x <= this.state.data.length && this.state.isFetched === true) {
            console.log(`trying ${x}`);
            var item = this.state.data[x];
            console.log(`success at ${ x }`);
            return (<Col className="store_product_wh" key={'goods_' + x} md={4}>
                <div className="store_product_photo margin-auto store_round_top_corners store_product_wh text-center">
                    <img src={item.photoSource} alt={'goods_' + x} />
                </div>
                <div className="store_product_block margin-auto store_round_bottom_corners store_product_w">
                    <p className="store_product_title text-center"><b>{item.title}</b></p>
                    <p className="store_product_price text-center">{item.price}</p>
                </div>
            </Col>);
        }
        else {
            return null;
        }
    }
    render() {
        var goods = [];
        for (var i = 0; i < this.state.data.length; i += 3) {
            if (i >= this.state.data.length) { break;}
            goods.push(
                <Row>
                    {this.buildGood(i)}
                    {this.buildGood(i + 1)}
                    {this.buildGood(i + 2)}
                </Row>)
        }
        return (
            <React.Fragment>
                <Container className="store_fluid" fluid={true}>
                    <h2 className="store_h2 noselect text-center">Store</h2>
                </Container>
                <Container>
                    {goods}
                </Container>

            </React.Fragment>
        );
    }
}

Мне пришлось вынести рендеринг одной карточки товара в отдельный метод buildGood(), так как если просто рендерить пачку <Col md={4}></Col>, то ничего хорошего не выходит - получается, что один товар в ряду. Поэтому я выбираю их по три и отправляю в массив goods, закрывая в <Row></Row>

В data четыре объекта, переданы нормально, всё проверял. Странное поведение циклов заключается в том, что когда он доходит до 4, он проходит цикл еще раз от 0 до 4 и выдает ошибку: item is not defined

Специально для того, чтобы проверить это, проставил console.log() и вот результат из консоли:

trying 0 main.chunk.js:2727:15
success at 0 main.chunk.js:2729:15
trying 1 main.chunk.js:2727:15
success at 1 main.chunk.js:2729:15
trying 2 main.chunk.js:2727:15
success at 2 main.chunk.js:2729:15
trying 3 main.chunk.js:2727:15
success at 3 main.chunk.js:2729:15
trying 4 main.chunk.js:2727:15
success at 4 main.chunk.js:2729:15
trying 0 main.chunk.js:2727:15
success at 0 main.chunk.js:2729:15
trying 1 main.chunk.js:2727:15
success at 1 main.chunk.js:2729:15
trying 2 main.chunk.js:2727:15
success at 2 main.chunk.js:2729:15
trying 3 main.chunk.js:2727:15
success at 3 main.chunk.js:2729:15
trying 4 main.chunk.js:2727:15
success at 4 
Answer 1

Не понял, в чем причина такого поведения, но переделал следующим образом:

buildGood(x) {
        if (x <= this.state.data.length && this.state.isFetched === true) {
            var item = this.state.data[x];
            return (<Col className="store_product_wh" key={'goods_product_' + x} md={4}>
                <div className="store_product_photo margin-auto store_round_top_corners store_product_wh text-center">
                    <img src={item.photoSource} alt={'goods_photosource' + x} />
                </div>
                <div className="store_product_block margin-auto store_round_bottom_corners store_product_w">
                    <p className="store_product_title text-center"><b>{item.title}</b></p>
                    <p className="store_product_price text-center">{item.price}</p>
                </div>
            </Col>);
        }
        else {
            return null;
        }
    }
    render() {
        var goods = [];
        if (this.state.data.length > 3) {
            var elementId = 0;
            var length = this.state.data.length - this.state.data.length % 3;
            for (var i = 2; i < length; i += 3) {
                goods.push(
                    <Row className="store_row" key={'goods_row_i_' + i}>
                        {this.buildGood(i - 2)}
                        {this.buildGood(i - 1)}
                        {this.buildGood(i)}
                    </Row>);
                length -= 3;
                elementId = i;
            }
            if (this.state.data.length % 3 > 0) {
                var goodlist = [];
                for (var j = 1; j < this.state.data.length - elementId; j++) {
                    goodlist.push(<React.Fragment key={'single_good_' + j}>{this.buildGood(elementId + j)}</React.Fragment>);
                }
                goods.push(<Row className="store_row ke" key={'goods_row_j_' + j}>{goodlist}</Row>);
            }
        }

READ ALSO
Оператор сравнения == и конструкция if [дубликат]

Оператор сравнения == и конструкция if [дубликат]

Столкнулся с таким нюансом, что if и конструкция var== false/true выдают разные результатыПожалуй, код продемонстрирует лучше слов:

177
HTML,CSS,JavaScript

HTML,CSS,JavaScript

Как сделать загрузку теста сделанный в блокноте и чтобы принимался и вставал по своим местам?

106
Получить значение input, а именно числовое значение, записанное в него с помощью класса

Получить значение input, а именно числовое значение, записанное в него с помощью класса

Как получить числовое значение, записанное в input, с помощью его класса? Или значение можно получить только используя id?

178
Перетаскивание OpenStreetMaps сквозь блок

Перетаскивание OpenStreetMaps сквозь блок

У меня поверх карты OpenStreetMaps находится divИ когда карта перемещается мышкой, то она так же перемещается сквозь блок

165