score:0

Accepted answer

So thanks to Dergash on Github I've discovered that the problem is not that my list is re-rendered.

Because I am creating a new URL every time with URL.createObjectURL inside of my component and because 'backgroundImage' does not do image prefetching whereas src attribute does I am seeing the flicker.

So my mistake was not creating the URL first and then passing it down into the component.

Working example: https://codesandbox.io/s/funny-http-8vrgv

More details: https://github.com/facebook/react/issues/16187

score:2

Array.map() allows dynamic rendering of elements in React, so that only those who change their props will re-render (as explained in the documentation).

If you'll use this method - rather than create the full array and render it fully - React will only re-render elements that are supposed to be updated:

props.images.map((imageFile, index) => {
    let objectURL = URL.createObjectURL(imageFile);

    const newStyles = { 
      left: `${leftPosition}%`,
      top: `${topPosition}%`
    }

    return (
      <div className="Preview" style={{...style, ...newStyles}} key={index}></div>
    )
});

Note that I've modified the key property of each element in the array. It should be unique and I didn't know what v4() is, so I just used the array indices.
React's documentation actually explains really well about these:

Keys help React identify which items have changed, are added, or are removed

score:2

Your answer is with 'key' property of react components. It's built for such cases Assuming this is render part of your component, you should have something like this:

return this.props.images.map(imageFile => (
    <div className="Preview" key={imageFile}></div>
))

Assuming imageFile is a unique string. This way react will rerender your virtual dom but it'll recognise that there is no need to dom update for same elements with same key property


Related Query

More Query from same tag