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 thanks. It is always all the way down when I look for something.
@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.
The second argument is still required. Third argument is the node to replace, second is where to mount.
See this issue: https://github.com/developit/preact/issues/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);
Gee, wouldn't it make more sense to make React's behavior the default, and then change behavior if there is a third argument?
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.
@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.
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
@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 馃憤
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
Most helpful comment
Gee, wouldn't it make more sense to make React's behavior the default, and then change behavior if there is a third argument?