Maybe I've missed something. If render is the proper way to generate code with Preact, I can't seem to figure out the proper way to generate and insert code out-of-order. What I mean: render appends.
For example:
render(<div>Post 1: Hello World</div>, document.body);
render(<div>Post 2: Blah Blah</div>, document.body);
Which outputs:
<div>Post 1: Hello World</div>
<div>Post 2: Blah Blah</div>
I want this instead:
<div>Post 2: Blah Blah</div>
<div>Post 1: Hello World</div>
Other than the obvious (switching the order), or inserting proxy elements that I target instead, what should I be doing in the 2nd line so it goes before the 1st element; Or specifically, so it inserts at the top of document.body instead of the bottom?
Thanks.
@povrazor Hmm - It's fairly odd to invoke render() multiple times for a single use-case. Is there a reason you want two top-level renders?
Normally your example would be written as a component:
class Example extends Component {
state = {
posts: [
{ title: 'Post 1', body: 'Hello World' },
{ title: 'Post 2', body: 'Blah Blah' }
]
};
render(props, state) {
// we can reverse-sort posts as part of the UI rendering:
let posts = state.posts.slice().reverse();
return (
<div>
{ posts.map( post => (
<div>
{post.title}: {post.body}
</div>
)) }
</div>
);
}
}
// finally, and generally only in one place per app, we initialize rendering:
render(<Example />, document.body);
edit: Sorry if I missed the point here, let me know if I answered the wrong question 馃槢
What I'm building is a bit twitter-like. It regularly polls a server for posts, and when there's something new, I need to insert the new posts at the top of the list.
I guess I missed the part where render is supposed to be a one-time call. :). Apparently I made a few too many assumptions about how I should be using Preact from the samples.
You can definitely re-render using render(), just you lose a lot of the benefits of component-based design. It's also mildly confusing because there is render() (import { render } from 'preact') and there is also a render() method on components.
Here's a little more fully-featured example continuing from above:
import { h, Component, render } from 'preact';
class App extends Component {
state = {
posts: [] // we'll keep all received posts in an array
};
// when App is mounted, start polling for updates
componentDidMount() {
this.getUpdates();
}
// fetches new posts, then calls itself (to poll)
getUpdates = () => {
fetch('/updates')
.then( r => r.json() )
.then( newPosts => {
// grab existing posts:
let { posts } = this.state;
// append new ones:
posts = posts.concat(newPosts);
// save updated posts to state (this automatically re-renders):
this.setState({ posts });
// wait a sec before polling again:
setTimeout(this.getUpdates, 1000);
});
}
// render gets called whenever state changes.
// The returned JSX gets intelligently diffed against the dom.
render(props, state) {
// we can reverse-sort posts as part of the UI rendering:
let posts = state.posts.slice().reverse();
return (
<div>
{ posts.map( post => (
<div>
{post.title}: {post.body}
</div>
)) }
</div>
);
}
}
// render and mount App. This kicks everything off.
render(<App />, document.body);
One thing worth noting: React/preact/etc actually simplify this kind of UI nicely, but it takes a little while to get used to the different way of doing things. Whereas with jquery/etc you might have to know "I want to insert new posts above existing posts", with this component model, you only have to tell it how to render _all_ posts (whether they are new or old). This way, determining whether new posts get injected first or last is simply a matter of choosing where to put them in an Array.
Awesome. Thank you so much for the example. I think state and setState was the other detail I misunderstood that tied this all together (the re-render).
Thanks again for your help!
Happy to help :) Hopefully I'll have some time to put better documentation together - I'd like to do some tutorials and such, perhaps on EggHead.io.
Most helpful comment
You can definitely re-render using
render(), just you lose a lot of the benefits of component-based design. It's also mildly confusing because there isrender()(import { render } from 'preact') and there is also arender()method on components.Here's a little more fully-featured example continuing from above:
One thing worth noting: React/preact/etc actually simplify this kind of UI nicely, but it takes a little while to get used to the different way of doing things. Whereas with jquery/etc you might have to know "I want to insert new posts above existing posts", with this component model, you only have to tell it how to render _all_ posts (whether they are new or old). This way, determining whether new posts get injected first or last is simply a matter of choosing where to put them in an Array.