Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOM elements duplicated on rerendering #49

Closed
capaj opened this issue Feb 13, 2016 · 14 comments
Closed

DOM elements duplicated on rerendering #49

capaj opened this issue Feb 13, 2016 · 14 comments

Comments

@capaj
Copy link

capaj commented Feb 13, 2016

So I have couple of boilerplate projects which show how to use https://github.com/capaj/systemjs-hot-reloader with different frameworks.
I wanted to get one for preact as well, but that proved harder than it should be.
First reason was your custom jsx which I think I can solve with @guybedford but the other one which you might help me with was something that bit me when I rerender a preact app.

I have this very simple hello world app: https://github.com/capaj/jspm-preact/blob/master/public/app.js#L13

All it does is render Hello world. Now when render is called second time(because we reloaded some module and want to refresh the app) it actually appends another Hello world into my 'app' div element. I haven't had any such behaviour with react. React render() always deterministically returns same DOM, overwriting the current elements.

Do you have any reason that this is how preact render method behaves? If not, could you please align the behaviour with react? Then I could drop this little hack: https://github.com/capaj/jspm-preact/blob/master/public/app.js#L16

Thanks for consideration.

@c2h5oh
Copy link
Contributor

c2h5oh commented Feb 13, 2016

https://github.com/developit/preact/wiki/Differences-to-React#whats-different

@capaj
Copy link
Author

capaj commented Feb 13, 2016

@c2h5oh thanks. It is always all the way down when I look for something.

@capaj
Copy link
Author

capaj commented Feb 13, 2016

@c2h5oh so I tried render(h(HelloWorld), null, document.getElementById('app')) but that is giving me

Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.

And if I do render(h(HelloWorld), document.getElementById('app'), document.getElementById('app')) that doesn't render anything.

@developit
Copy link
Member

The second argument is still required. Third argument is the node to replace, second is where to mount.

See this issue: #24

Let me know if that doesn't solve it for you.

- edit -
So your example would be:

let parent = document.getElementById('app');
// call this as often as you want:
render(h(HelloWorld), parent, parent.lastChild);

@qwertie
Copy link

qwertie commented Apr 29, 2018

Gee, wouldn't it make more sense to make React's behavior the default, and then change behavior if there is a third argument?

marvinhagemeister added a commit that referenced this issue Mar 2, 2019
Refactor component diff to save some bytes
@ayZagen
Copy link

ayZagen commented Sep 2, 2020

I definitely agree with @qwertie. I am trying to migrate my gatsby site to preact and I couldn't find any way to pass replaceNode argument. I think this line here makes it impossible to pass the argument as gatsby uses preact/compat under hood.

@marvinhagemeister
Copy link
Member

@ayZagen React's behaviour has been the default in Preact since the beginning of the 10.x release line, which started more than a year ago. You don't need to pass the third parameter anymore to match that behavior.

@ayZagen
Copy link

ayZagen commented Sep 2, 2020

Thanks for the quick reply. I have tried 10.4.8 and faced with this issue. This is the component:

const HttpSnippet = ({ request, language, codeRef }) => {

  const harRequest = createHarFromOpenApiRequest(request, language)
  const snippet = new SnippetCreator(harRequest)
  const code = snippet.convert(language)
  const lineCount = code.split(/\r\n|\r|\n/).length

  useEffect(()=>{
    Prism.highlightAll()
  }, [language])

  return (
    <>
      <div className="line-counts">
        { Array(lineCount).fill().map((count, index) => (<div key={index}>{index + 1}</div>))}
      </div>
      <pre>
          <code className={`language-${language}`} key={language} ref={codeRef}>{ code }</code>
      </pre>
    </>
  )
}

code element textContent gets duplicated on every rerender

@marvinhagemeister
Copy link
Member

@ayZagen That sounds indeed like an issue. Can you open a new one?

This one is for a different release line and has long been fixed. Even though the symptoms look similar it's probably a different issue. A codesandbox or a repo where the issue can be reproduced is an incredible helpful thing in getting to the bottom of it. Strongly recommend including that 👍

@ayZagen
Copy link

ayZagen commented Sep 2, 2020

I couldn't reproduce issue with only preact. Using Prism.highlightAll() breaks it. I will look into prismjs and will try to reproduce the issue

@jakedee
Copy link

jakedee commented Jul 27, 2021

@ayZagen Did you ever find out what was causing this issue? I'm seeing something similar to what you're describing.

@ayZagen
Copy link

ayZagen commented Jul 27, 2021

@jakedee sorry, I couldn't dig deep for it and migrated back to react in our gatsby project.

@marvinhagemeister
Copy link
Member

@jakedee Can you open a new issue for that?

@jakedee
Copy link

jakedee commented Jul 28, 2021

@marvinhagemeister - #3236

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants