Search code examples
reactjsrenderinglifecycle

React high order funtion to insert random image not working when re-rendering


I have a really simple HOC whose code is

import React from 'react';

const withRandomImage = Comp => props => {
  const x = Math.floor(Math.random() * 26);
  return <Comp {...props} image={x} /> 
}

export default withRandomImage;

It works with an ImageBar component whose code is

import React from 'react';
import styled from 'styled-components';

import withRandomImage from '../../hocs/WithRandomImage';

const Bar = styled.div`
    display: block;
    height: 310px;
    background-image: url(${props => props.image});
    background-size: cover;
    background-position: 0px -400px;
    background-repeat: no-repeat;
`

const formatWrapper = {
    width: "100%",
    height: "310px"
}

class ImageBar extends React.Component {

    getBgImage = () => {
        console.log(window.location.origin);
        return window.location.origin + '/hp/' + this.props.image + '.jpg';
    }

    render() {
        console.log("Image: ",this.getBgImage());
        return (
            <Bar className="ImageBar" image={this.getBgImage()}>
                <div className="container-fluid">
                    <div className="row align-items-center" style={formatWrapper}>
                        {this.props.inner}
                    </div>
                </div>
            </Bar>
        )
    }
}

export default withRandomImage(ImageBar);

The idea is having a random image served as background image every time the page is refreshed. Images are served from /hp/ folder inside React's public directory.

Everything works fine when the component is rendered for the first time. But inside this ImageBar I have some components (passed in this.props.inner) with event listeners attached to them. Every time an event id triggered the background image disappears.

This is an example of a component where this ImageBar is rendered.

render() {
    return (
        <div>
            <Header />
            <ImageBar inner={this.getSearchBar()} />
        </div>
    )
}

I think this is something related to the components lifecycle, but can't figure exactly what is happening.

Any suggestions?


Solution

  • I think math.random() * 26 is generating an url that does not have a proper image in your hp folder. Have you checked that?

    Keep in mind every render will generate a new random value, and a new prop. You can "freeze it" to the "first" generated value by moving out the generation of the number outside of your enhanced component.

    Something along the lines of

    const withRandomImage = Comp => {
        const x = Math.floor(Math.random() * 26);
        // when rereder occurs, only the code below will be run - so the image is always the same
        return props => <Comp {...props} image={x} />
    }