0

I have two components, let's say componentA and componentB. Both component import a .gif file, let's say image.gif. image.gif does not loop, so it should be played once only if it's not updated.

Initially componentA renders image.gif but not componentB. So the image.gif inside componentA is played once. When I render image.gif inside componentB, image.gif inside componentA is played again, which is not wanted.

Can it be done? Thanks!

Edit: Some simple codes for reproducing:

Component A import image as './image.gif'

export default class componentA extends React.PureComponent {
    render() {
        return (
            <div>
                <img src={image} />
            </div>
        );
    }
}

Component B import image as './image.gif'

export default class componentA extends React.PureComponent {
    render() {
        return (
            <div>
                {this.props.show ? <img src={image} /> : null}
            </div>
        );
    }
}

App

import componentA from './componentA.react'
import componentB from './componentB.react'

export default class App extends React.Component {

    componentWillMount() {
        this.setState({
            show: false,
        });
    }

    componentDidMount() {
        // ...or some moment when the App thinks componentB should update
        this.setTimeout(() => {
            this.setState({
                show: true,
            });
        }, 4000);
    }

    render() {
        return (
            <componentA />
            <componentB show={this.state.show} />
        );
    }
}
Theogry
  • 266
  • 2
  • 7

2 Answers2

0

I'd suggest to use a bit more complex (and more flexible) structure: use static and animated gifs and swap them with javascript.

Like was suggested in similar cases:

Stop a gif animation onload, on mouseover start the activation

JavaScript to control image animation?

LazyGreg
  • 1
  • 1
  • But if I have different ending times for different gifs (and loading them dynamically), I will have to record the ending time of each gif, which may even be impossible for me. – Theogry Oct 21 '17 at 12:35
0

As this.setState runs the this.render method, your 2 components are rerendered.

You can try the following :

Component A :

export default class componentA extends React.Component {
    render() {
        return (
            <div>
                <img src={image} />
            </div>
        );
    }
}

Component B :

export default class componentB extends React.Component {
    constructor () {
        super(props)
        this.state = { show: false }
    }

    componentDidMount() {
        this.setTimeout(() => {
            this.setState({
                show: true,
            });
        }, 4000);
    }

    render() {
        return (
            <div>
                {this.state.show ? <img src={image} /> : null}
            </div>
        );
    }
}

App :

import componentA from './componentA.react'
import componentB from './componentB.react'

export default class App extends React.Component {
    render() {
        // Carefull here, you have to return a single `node` in the render method
        return (
            <div>
                <componentA />
                <componentB />
            </div>
        );
    }
}
3Dos
  • 3,210
  • 3
  • 24
  • 37
  • Sorry for misleading you, some points: 1. componentA and componentB is actually extending React.PureComponent, so they won't re-render unless the props has changed (so componentA should never re-render) 2. The timeout should be controlled by Grid, as componentB should never know when the gif should be loaded. Apologies for mistakes. – Theogry Oct 21 '17 at 12:41
  • Oh alright, my knowledge of PureComponent is equal to null ! I'll give it a look though ! – 3Dos Oct 21 '17 at 12:46
  • Looks like it will render with PureComponent anyway as I read in the [docs](https://reactjs.org/docs/react-api.html#reactpurecomponent) the following: If your React component’s render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases. As your state changes, I think it actually rerenders everything ! That's why I moved the state in ComponentB to try to solve your issue ! – 3Dos Oct 21 '17 at 13:26
  • https://reactjs.org/docs/react-component.html#shouldcomponentupdate if the state does not change, react PureComponent does not re-render. – Theogry Oct 21 '17 at 13:58
  • And what do you this this.setState does ? Put a consol.log('renders'); in your render method and you'll see. – 3Dos Oct 21 '17 at 13:59
  • I tried to put a console.log('render') in each of the component. It logs three times in total, two for the initial render of each component, and the third when componentB updates. – Theogry Oct 21 '17 at 14:19