Search code examples
javascriptreactjsimagereact-dom

Detect broken image when using hydrate instead of render from react-dom


We are using hydrate from react-dom in a project and are having a hard time detecting broken image links. These images come from a 3rd party API so we have no way of knowing which links work beforehand.

export default class Image extends PureComponent {
  render() {
    return (
      <img
        src={this.props.src}
        onError={(e) => {  
          e.target.src='https://mycdn.com/fallback.jpg';
        }}
      />
    )
  }
}

The above code works if we use render instead of hydrate. Is there a way to detect broken images when using hydrate?


Solution

  • Unfortunately, ReactDOM.hydrate does not attach the onLoad or onError events.

    The best method I can think of is doing a sort of 2-pass rendering. From the server, always render the fallback (or a placeholder) image. On the client, use componentDidMount and state to update the image's src to the real source.

    export default class Image extends PureComponent {
      state = { isMounted: false }
    
      componentDidMount() {
        this.setState({ isMounted: true });
      }
    
      render() {
        return (
          <img
            src={ isMounted ? this.props.src : this.props.fallbackSrc }
            onError={(e) => {  
              e.target.src = this.props.fallbackSrc;
            }}
          />
        );
      }
    }
    

    Since the server doesn't call the componentDidMount lifecycle, it will always render the fallback image.

    After the hydrate completes and the component is mounted, it will update the state triggering a rerender that will then use the real src from props.