Closed GordonCode25 closed 2 years ago
Hi 👋
Try returning list
directly from P.render()
instead of {list}
. Currently the code above is returning an object with a single list
property. A Component's render()
method should return a preact VNode (the value returned from calling createElement
) or a list of VNodes (like you are doing here).
See if that helps :)
Sorry, thought I'd updated that example. I'm testing with <div>{list}</div>
and it's the same issue. It just removed the divs from the example markup for some reason.
Also note, if I add multiple items to the list, it still doesn't work.
This works for me https://codesandbox.io/s/headless-dew-s44bm?file=/src/index.js
So the problem I'm having is the diff. It works first time, but second time it's blank.
preact.render(preact.createElement(P,{test:"A"}), root,root.firstChild);
preact.render(preact.createElement(P,{test:"B"}), root,root.firstChild);
Oh yes, This is a current limitation of replaceNode
a workaround you can use is wrapping the <p>{test}</p>
in a <Fragment key={test}
or just make it into it's own component. In the replaceNode
process it's hard to reconcile keyed native nodes.
ok, sounds like you've seen this issue before. Can you explain that a little more clearly or point me at some documentation?
I need to wrap something in a fragment with a key? What do I need to wrap, why?
A little background, I'm maintaining a pretty huge app, I've just updated the version of preact and I'm seeing blank bits appearing all over the place. This example is just for demonstration.
@GordonCode25 If you're just updating from Preact 8.x there is a high chance you can just remove the third argument to render()
, see this page in our docs.
I think removing the last argument works but wouldn't that re-render my entire page?
Also, would be nice to understand where I'm going wrong.
So the issue presents itself because we use a key on the p tag, we enter the render cycle with the tag inside of excessDomChildren and in oldChildren our diffElementNodes sees that we can reuse this paragraph but does not remove it from oldChildren meaning we'll unmount it later in the cycle.
This means that if we wrap this in a function like
const Text = ({ content }) => <p>{content}</p>
const App = ({ test }) => {
const list = [<Text key={test} content={test} />]
return <div>{test}</div>
}
// OR
const App = ({ test }) => {
const list = [<Fragment key={test}><p>{test}</p></Fragment>]
return <div>{test}</div>
}
ok, thanks guys. Appreciate the help.
Further note on this, still couldn't get it to work but I eventually managed to find a workaround.
I created a Root component and used an event to update the the state on the Root component rather than calling render again.
This seems similar to the issue we were having with replaceNode
in htm/preact
. Removing that parameter fixed the issue, but it makes me wonder if something is awry still.
Closing as inactive
I'm trying out the latest version of preact UMD but I'm struggling with an issue I didn't seem to have before where components don't render every other time they are replaced. Here is an example?
Component
This script runs client side (Simulating loading a new page)
The rendered content gets loaded into this root div.
Note: I'm aware of using => for loops, it's just a coding pattern I use for complex lists.