Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering react component after api response

I have a react component that I wish to populate with images using the Dropbox api. The api part works fine, but the component is rendered before the data comes through & so the array is empty. How can I delay the rendering of the component until it has the data it needs?

var fileList = []; var images = []; var imageSource = [];  class Foo extends React.Component {   render(){   dbx.filesListFolder({path: ''})   .then(function(response) {    fileList=response.entries;    for(var i=0; i<fileList.length; i++){     imageSource.push(fileList[0].path_lower);    }    console.log(imageSource);    })    for(var a=0; a<imageSource.length; a++){    images.push(<img key={a} className='images'/>);   }    return (    <div className="folioWrapper">     {images}    </div>   );  } } 

Thanks for your help!

like image 882
r_cahill Avatar asked Jul 04 '17 16:07

r_cahill


People also ask

How do you force render a component in React?

Forcing an update on a React class component In any user or system event, you can call the method this. forceUpdate() , which will cause render() to be called on the component, skipping shouldComponentUpdate() , and thus, forcing React to re-evaluate the Virtual DOM and DOM state.


2 Answers

Changes:

1. Don't do the api call inside render method, use componentDidMount lifecycle method for that.

componentDidMount:

componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request. Setting state in this method will trigger a re-rendering.

2. Define the imageSource variable in state array with initial value [], once you get the response update that using setState, it will automatically re-render the component with updated data.

3. Use the state array to generate the ui components in render method.

4. To hold the rendering until you didn't get the data, put the condition inside render method check the length of imageSource array if length is zero then return null.

Write it like this:

class Foo extends React.Component {      constructor(){         super();         this.state = {             imageSource: []         }     }      componentDidMount(){         dbx.filesListFolder({path: ''})           .then((response) => {               let fileList = response.entries;               this.setState({                   imageSource: fileList               });           })     }      render(){         if(!this.state.imageSource.length)             return null;          let images = this.state.imageSource.map((el, i) => (             <img key={i} className='images' src={el.path_lower} />         ))          return (             <div className="folioWrapper">                 {images}             </div>         );     } } 
like image 129
Mayank Shukla Avatar answered Sep 19 '22 12:09

Mayank Shukla


You should be using your component's state or props so that it will re-render when data is updated. The call to Dropbox should be done outside of the render method or else you'll be hitting the API every time the component re-renders. Here's an example of what you could do.

class Foo extends React.Component {   constructor(props) {     super(props);     this.state = {       imageSource: []     }   }    componentDidMount() {     dbx.filesListFolder({ path: '' }).then(function(response) {       const fileList = response.entries;        this.setState({         imageSource: fileList.map(file => file.path_lower);       })     });   }    render() {     return (       <div className="folioWrapper">         {this.state.imageSource.map((image, i) => <img key={i} className="images" src={image} />)}       </div>     );   } } 

If there are no images yet, it'll just render an empty div this way.

like image 36
DonovanM Avatar answered Sep 19 '22 12:09

DonovanM