0

What I am trying to do grab json data to render it as an element. Here is what I have, but this.images continues to come up empty(and undefined/null if I don't set it at the top.

import React, { Component } from 'react';
import axios from 'axios';

export default class Grid extends Component {
  constructor(props) {
    super(props);
    this.images = [];
  }

  componentWillMount() {
    axios.get('grid-config.json')
    .then((res) => {
      this.setImageArray(res.data);
    });
  }

  setImageArray(imageArray) {
    let newArray = [];
    for(let i = 0; i < imageArray.length; i++) {
      newArray.push(imageArray[i]);
    }
    this.images = newArray;
   }


  render() {
    const postData = this.props.images;
    console.log(this.images);
    return (
      <div>
       hello
      </div>
    );
  }
}
2
  • Could you please check the browser console and see if there's any error there? Commented Aug 7, 2017 at 11:37
  • There is not, I checked. The only thing in the console is [] --> which is for console.log(this.images) Commented Aug 7, 2017 at 11:41

3 Answers 3

3

You should use the component's state to hold the image data; when this is updated it will cause the component to render (React will call its render function.)

So, for example, set the component's state something like this:

    setImageArray(imageArray) {
    let newArray = [];
    for(let i = 0; i < imageArray.length; i++) {
      newArray.push(imageArray[i]);
    }
    this.setState({images: newArray });
   } 

and also initialise this, for example, in the component's constructor:

constructor(props) {
    super(props);
    this.state = { images: [] };
  }

You access the data in the render function as this.state.images.

{See the section entitled A Stateful Component at https://facebook.github.io/react/ }

Sign up to request clarification or add additional context in comments.

1 Comment

Small typo in your code, this.setState({ images: newArray }).
0

in this case you must only manipulate with your state instead of class property. Use setState method to update your component state. And render images from your updated state.

export default class Grid extends Component {
  constructor(props) {
   super(props);
   this.state = { images: [] };
  }

 componentWillMount() {
  axios.get('grid-config.json')
   .then((res) => {
    this.setImageArray(res.data);
  });
 }

 setImageArray(imageArray) {
  let newArray = [];
  for(let i = 0; i < imageArray.length; i++) {
    newArray.push(imageArray[i]);
  }
  this.setState({ images: newArray });
 }


 render() {
  const postData = this.state.images;
  console.log(postData);
  return (
   <div>
    hello
   </div>
  );
 }
}

Try this code to render images;

Comments

0
  1. React components will call render only if the state is changed (except in special cases like initial render or when forceUpdate is called).

  2. Your axios call is async and component is already rendered by the time it executes.

  3. Thus, the render function is called when images is [], and never called again.

  4. To force a re-render, you have to store the response in state, as pointed in multiple answers or use forceUpdate (not recommended).

EDIT

class Application extends React.Component {
  constructor(props) {
    super(props)
    this.myName = "Sachin"
  }

  componentDidMount() {
    setTimeout(() => {
      this.myName = 'Jamie';

      // If this is commented out, new value will not reflect in UI.
      this.forceUpdate()
    })
  }
  render() {
    return (
      <div>
        <h1>Hello, {this.myName}</h1>
      </div>
    );
  }
}

See this code pen link : https://codepen.io/sach11/pen/ayJaXb

Its very similar to your code, just replaced axios call with a setTimeout.

On line 16, I have a forceUpdate(), which forces a re-render and reflects the new value of this.myName. Otherwise although value is updated, it does not reflect as render is not called again.

3 Comments

When I console.log(this) in the render function though it prints with the image object in it. Why is that?
@Jamie as I already pointed out, 'images' is added to the class instance as soon as you define it in constructor. But its values get populated only after axios call is completed. Thus, 'this' has a property called 'image', but in first render its value will be '[]'. If you can trigger render function again, you will see the actual values inside it.
@Jamie I've updated my answer with a codepen link, check that out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.