preact-cli
preact-cli copied to clipboard
Serialize and hydrate data from prerender-urls on the client.
It would be good if we could detect that prerender-urls has passed more than { url, title } as the data for a given route, and serialize that into the HTML:
<script type="text/props" id="appprops">
{ "url": "/profile/john", "profile": { "name": "John Doe" } }
</script>
Then we can pass these to <App /> when booting on the client.
Just to add on to this, it would be great to see a canonical and documented way to use serialized and hydrated data inside component templates between npm start (dev) and npm run build --prerender-urls (prod build). Currently the only way I've found is to save the data to state inside the application component and then have some verbose templating syntax for fallthrough
app.js
let INIT = {};
if (typeof document!=='undefined') {
try {
INIT = JSON.parse(document.getElementById('app_props').textContent) || {};
console.log(INIT, 'whyy tho')
} catch (e) {console.error(e)}
}
export default class App extends Component {
constructor(props) {
super(props);
this.init = INIT || props;
console.log(this.init);
}
/** Gets fired when the route changes.
* @param {Object} event "change" event from [preact-router](http://git.io/preact-router)
* @param {string} event.url The newly routed URL
*/
handleRoute = e => {
this.currentUrl = e.url;
this.fetchOrSetData();
};
fetchOrSetData() {
if (this.currentUrl === this.init.url && this.init.data) {
this.setState({data: this.init.data});
}
else {
fetch('http://www.filltext.com?rows=10&f={firstName}').then(res => {
const json = res.json();
return json;
}).then(data => {
console.log('data fetced', data[0].f);
return this.setState({data: {name: data[0].f}});
});
}
}
render() {
return (
<div id="app">
{typeof window==='undefined' &&
<script type="text/props" id="app_props" dangerouslySetInnerHTML={{__html: JSON.stringify({ url: this.props.url, data: this.props.data })}}></script>
}
<h1>Hello Yes: {this.props.data && this.props.data.name || this.state && this.state.data && this.state.data.name}</h1>
<Router onChange={this.handleRoute}>
<Redirect path="/" to="/menu"/>
<Menu path="/menu" url={this.currentUrl}/>
<Work path="/work" url={this.currentUrl}/>
</Router>
</div>
);
}
}
Imagine that every single piece of text content on a site was authored in a cms: Every template binding would need something along the lines of this:
{this.props.data && this.props.data.name || this.state && this.state.data && this.state.data.name}
@developit had an idea to monkey patch fetch
This could be an implementation but still not sure on how to do this at scale of the entire site's content?
Nice to see this on the table. I'm currently using https://github.com/nozzle/react-static and wanted to switch to preact, but I really need this feature.
For example, I have a lot of pages that all share the same component, but with different data. The tricky is also where the url is more flexible than would be convenient in preact.
Take these routes:
- /product/doll/white
- /product/doll/black
- /product/puppet/white/large
- /product/puppet/white/small
- /product/puppet/black/large
- /product/puppet/black/small
All these routes would use the Product component, and the amount of sections in the path is completely arbitrary. This makes it rather annoying to configure a Router in code and it would be nice to let the Router generate all these routes based on said data.
Yeah for me that's the thing we have to figure out, parity between dev and build for this data
Also it wouldn't get fetched after route changes currently
It's initial data to hydrate from, but nothing more
We don't want to write these out as files, do we? ("static API routes"?)
build/product/doll/white
build/__preact_data/product/doll/white.json