Possible bug?
When dynamically rendering a list of <div> or <img> elements - each new addition re-renders the entire list ONLY if just background-image is specified. If Img.src is specified normal behavior occurs.
Example:
https://codesandbox.io/s/brave-mcnulty-0rrjz
Relevant comments and code are at Preview.js:55
This is a lot of code to debug, could you simplify it down to something with redux and all the bits not relevant to this?
I don't have the time, sorry.
Hello @colemars! I don't think it's a bug.
You assign "style" property for your image like this:
props.images.images.map((imageFile, index) => {
let objectURL = URL.createObjectURL(imageFile);
const bugStyles = {
backgroundImage: `url(${objectURL})`,
left: `${leftPosition}%`,
top: `${topPosition}%`
};
<img style={{ ...style, ...bugStyles }} />
})
But URL.createObjectURL(imageFile) creates a different string every time.
The backgroundImage field in bugStyles object changes every time for all images, and when reconciliation happens React decides it's a different object and element should rerender, because the property have changed.
edit: Apparently my understanting of 'style' property was wrong :) Reconciliation doc says that 'style' is a special case and should update changed css attributes directly instead of recreating the node.
So now I think that in your example entire list it not actually rerendered, you just see images flickering because image urls are different every time and 'backgroundCss' does not do image prefetching like src attribute does.
The entire list rerender would have looked like this (notice that img tags are highlighted, it means they have been rerendered):

When in fact you have this (notice that img tags are not higlighted, it means they have not been rerendered but still flicker):

You probably should create url once, when the image is uploaded.
Here is an example where I moved your URL.createObjectURL(imageFile) from list render to image uploade method (PastImageInput.js):
https://codesandbox.io/s/funny-http-8vrgv
Thank you so much! This is a great overview that helps me understand reconciliation better. And that visual is great - you've added to my trove of tricks to use when playing around with React.
I'll close this now. Apologies for my misunderstanding!
Most helpful comment
Hello @colemars! I don't think it's a bug.
You assign "style" property for your image like this:
But URL.createObjectURL(imageFile) creates a different string every time.
The backgroundImage field in bugStyles object changes every time for all images, and when reconciliation happens React decides it's a different object and element should rerender, because the property have changed.edit: Apparently my understanting of 'style' property was wrong :) Reconciliation doc says that 'style' is a special case and should update changed css attributes directly instead of recreating the node.
So now I think that in your example entire list it not actually rerendered, you just see images flickering because image urls are different every time and 'backgroundCss' does not do image prefetching like src attribute does.
The entire list rerender would have looked like this (notice that img tags are highlighted, it means they have been rerendered):


When in fact you have this (notice that img tags are not higlighted, it means they have not been rerendered but still flicker):
You probably should create url once, when the image is uploaded.
Here is an example where I moved your URL.createObjectURL(imageFile) from list render to image uploade method (PastImageInput.js):
https://codesandbox.io/s/funny-http-8vrgv