Reputation: 1117
Have a look my code below, I have create a pen for it too: https://codepen.io/segmentationfaulter/pen/YEEaxK
The problem is that when I click on change image
button, the old image stays there for a while until the new image is loaded. What I want is that the old image is invalidated straight away and empty space is shown for the new image. How can I achieve this in react? If you can't spot the issue, try opening it in private mode so that caching doesn't affect it.
const images = [
'http://via.placeholder.com/550x550',
'http://via.placeholder.com/750x750'
]
class MyImage extends React.Component {
constructor() {
super()
this.state = {
currentImageIndex: 0
}
}
changeImage() {
this.setState((prevState) => {
if (prevState.currentImageIndex) {
return {
currentImageIndex: 0
}
} else {
return {
currentImageIndex: 1
}
}
})
}
render() {
return ( <
div >
<
img src = {
this.props.images[this.state.currentImageIndex]
}
/> <
button onClick = {
this.changeImage.bind(this)
} >
change image <
/button> <
/div>
)
}
}
ReactDOM.render( < MyImage images = {
images
}
/>, document.getElementById('root'))
img {
display: block;
}
button {
margin-top: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root">
<div>
Upvotes: 1
Views: 1008
Reputation:
Possible way may be:
put empty picture if state is changed
fetch the image and then replace empty image from response
Upvotes: 0
Reputation: 7424
You could use, for example, onLoad
prop from img
where you toggle a loading
in state so you can render the placeholder.
The strategy around it is:
loading
is true
PS: I added a timeout so you can see the placeholder in action.
const images = [
'http://via.placeholder.com/550x550',
'http://via.placeholder.com/750x750'
]
class Images extends React.Component {
constructor() {
super()
this.state = {
currentImageIndex: 0,
loading: true,
}
}
handleLoad() {
setTimeout(() => {
this.setState({ loading: false })
}, 1000)
}
changeImage() {
this.setState((prevState) => {
if (prevState.currentImageIndex) {
return {
currentImageIndex: 0
}
}
return {
currentImageIndex: 1
}
})
}
render() {
const { loading, currentImageIndex } = this.state
return (
<div>
{loading && <div>placeholder comes here</div>}
<img
onLoad={this.handleLoad.bind(this)}
src={images[currentImageIndex]}
style={{ display: loading ? 'none' : 'block' }}
/>
<button onClick={this.changeImage.bind(this)}>
change image
</button>
</div>
)
}
}
ReactDOM.render(
<Images />,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Upvotes: 1
Reputation: 169
Try to assign a random key
prop to the img element every time it switches to another image. This forces react to recreate the element.
constructor () {
super()
this.state = {
currentImageIndex: 0,
imgKey: Math.random()
}
}
changeImage () {
this.setState((prevState) => {
if (prevState.currentImageIndex) {
return { currentImageIndex: 0, imgKey: Math.random() }
} else {
return { currentImageIndex: 1, imgKey: Math.random() }
}
})
}
render () {
return (
<div>
<img key={this.state.imgKey} src={this.props.images[this.state.currentImageIndex]} />
<button onClick={this.changeImage.bind(this)}>
change image
</button>
</div>
)
}
}
Upvotes: 3