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!
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.
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> ); } }
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With