Preact: Render's replaceNode Argument Ignored

Created on 3 May 2020  ยท  9Comments  ยท  Source: preactjs/preact

Reproduction

I spotted in the docs for the render that you can supply an optional third argument replaceNode which will be diffed during the initial render. It seems in the most recent version that this behaviour does not work.

In this CodePen for version 10.4.1 I would expect the placeholder span to be replaced with the bar component. Instead the bar component is prepended into the container.

The last version I could find which had the behaviour described in the docs was v8.5.3 (CodePen).

Steps to reproduce

Expected Behavior

As per this CodePen using version v8.5.3 and from the docs i expected the replace node to be removed from the DOM during the initial render.

Actual Behavior

The placeholder span passed into render as the replaceNode was not removed from the DOM.

discussion enhancement known issue workaround

Most helpful comment

In Preact X, replaceNode (as does hydration) expects your dom to be equal else it has to fallback to a regular render. Which is something we haven't implemented yet. if you'd render a span in your example instead of a div you would see the expected result. We might want to document this

All 9 comments

In Preact X, replaceNode (as does hydration) expects your dom to be equal else it has to fallback to a regular render. Which is something we haven't implemented yet. if you'd render a span in your example instead of a div you would see the expected result. We might want to document this

Like @JoviDeCroock said, the third parameter doesn't account for element mismatch. Using the same element will fix it.

Ahh ok. Switching the span for a div does indeed make it work on my codepen. Thanks for the info!

At least to me, that is a little counter intuitive. Maybe because I am new to preact from react where the content of the container is replaced by your component tree by default. The docs for replaceNode seemed to be the way to prompt it to behave similarly, but it sounds like that is more like an upcoming thing for X...

I would love to suggest that I could submit an MR to update the docs for you butIi'm not sure I know enough about preact to be accurate yet... :grimacing:

In the meantime thanks again for your help!

@jayseeare rendering without the thirth argument should do so, replaceNode is meant if you want to keep adjacent children intact.

Imagine:

<div id="root">
  <some generic header>
  <div id="render-here">
  <some generic footer>
</div>

Then we can call render(<App />, root, renderHere) to preserve our header and footer.

Hmmm... That does make sense. Sounds like that would come in handy in some cirumstances. However not seeing the placeholder replaced is how i started this journey...

See this fork of my 10.4.1 codepen: https://codepen.io/jayseeare/pen/gOaoYXe

I'm doing:

const { h, render } = preact;
/** @jsx h */

const Foo = ({text}) => <div>Bar:{text}</div>;

render(
  <Foo text="hello"/>, 
  document.getElementById('container')
);

And the placeholder remains after the render. It looks like to get the behaviour you describe you again need to switch the placeholder from a span to a div. Is that expected?

Yes because it behaves like a hydrate, we should fallback to normal render mode if we seee a missmatch.

Ahh yeah of course - same deal, different target. Thanks for clarifying! :)

No problem, glad I could help and thanks for pointing us to it. We'll probably have a conversation about adding this functionality if it doesn't impose any issues down the road!

No need for thanks. Thanks for the library and support!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

matuscongrady picture matuscongrady  ยท  3Comments

jasongerbes picture jasongerbes  ยท  3Comments

simonjoom picture simonjoom  ยท  3Comments

skaraman picture skaraman  ยท  3Comments

SabirAmeen picture SabirAmeen  ยท  3Comments