Preact: Diff doesn't render anything.

Created on 22 Apr 2020  路  14Comments  路  Source: preactjs/preact

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

class P extends Component {

    constructor(props) {
        super(props);
    }

    render() {
        var test = this.props.test;
        var list=[];
        list.push(<p key={test}>{test}</p>);
        return <div>{list}</div>;
    }

}

This script runs client side (Simulating loading a new page)

var root = document.getElementById("root");
preact.render(preact.createElement(P,{test:"A"}), root,root.firstChild);
preact.render(preact.createElement(P,{test:"B"}), root,root.firstChild);

The rendered content gets loaded into this root div.

<div id="root"><div className="seo">SEO text...</div></div>

Note: I'm aware of using => for loops, it's just a coding pattern I use for complex lists.

needs-more-info

All 14 comments

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.

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nopantsmonkey picture nopantsmonkey  路  3Comments

KnisterPeter picture KnisterPeter  路  3Comments

Zashy picture Zashy  路  3Comments

kossnocorp picture kossnocorp  路  3Comments

skaraman picture skaraman  路  3Comments