Captain
Captain

Reputation: 133

The React variable changes, but it is not rendered... why?

I am a newby in React, and I have a problem with the following code:

import React, { Component } from 'react';
import banner from './images/banner.png';
import logo from './images/logo.png';
import coin from './images/coin.png';
import './App.css';
var $ = require('jquery');


function CardItem(props) {
  return (
                    <li>
                        <div className="imageWrapper">
                            <img/>
                        </div>
                        <h3>Title</h3>
                        <p>Category</p>

                    </li>
  );
}


class Cards extends Component {

  constructor() {
    super();

    let items = [];
    this.items = items;

     $.ajax({
      url: '//localhost:3004/products',
      dataType: 'json',
      success: function(data) {

       items.push(data);

      },
      error: function(xhr, status, err) {
         console.log("\nError:" + err);

      }
    });
  }

    render(){


        var itemsList = this.items.map(function(oneItem){

            return <CardItem/>;
        });



        return (

                <section>
                    <h2>{this.items.length} Products</h2>

                    <ul>
                {itemsList}     

                    </ul>
                </section>
        );
    }
}


class App extends Component {
  render() {
    return (


        <div className="App">
            <header>
                <img className="logo" src={logo}/>
                <img className="banner" src={banner}/>


            </header>

            <Cards/>

        </div>


    );
  }
}

export default App;

It's supposed the web browser should show the list of the array items, but instead of that it shows nothing, just like the array was empty.

When the callback changes the variable items, what I see in the browser doesn't update. What I am doing wrong?

Upvotes: 2

Views: 124

Answers (1)

Dmitry Druganov
Dmitry Druganov

Reputation: 2358

Two problems that I see:

  1. items.push(data) will actually append the array of products as an item to your items array. Use this.items = this.items.concat(data) instead.

  2. You need to re-render your component when data is received. So I would better keep your items in the component state: call this.setState({ items: data }) in success callback (that will trigger re-rendering) and use this.state.items in the render() method instead of this.items

And as Rohitas said, do your AJAX requests in componentDidMount

So your Cards component could be something like:

import fetch from 'cross-fetch';

// ...

class Cards extends Component {

  constructor() {
    super();
    this.state = {
      items: [],
    };
  }

  componentDidMount() {
    fetch('//localhost:3004/products')
      .then(res => {
        if (res.status >= 400) {
          console.error('Unable to fetch products', res);
        } else {
          res.json()
            .then(items => this.setState({ items });
        }
      });
  }

  render() {
    return (
      <section>
        <h2>{this.state.items.length} Products</h2>
        <ul>
          {this.state.items.map(item =>
            <CardItem {...item} />)}
        </ul>
      </section>
    );
}

Upvotes: 3

Related Questions