I think I'm conceptually missing something with server-side rendering using React.js
Assume I want to create a page to display items from a server-side DB, with an input field to filter them.
I want a page:
/items?name=foobar
Assume I have a public REST API to query the items on the client side.
Conceptually, what I want to do at first request (GET /items?name=foobar
) is :
initialName
)So I tried this:
// A stateful component, maintaining the value of a query field
var ItemForm = React.createClass({
getInitialState : function () {
return {
name : this.props.initialName
};
},
handleInputValueChanged : function() {
var enteredName = this.refs.query.getDOMNode().value.trim();
this.props.onNameChanged(enteredName);
},
render : function () {
return React.DOM.form({
children : [
React.DOM.label({
children : "System name"
}),
React.DOM.input({
ref : "query",
value : this.state.name,
onChange : this.handleInputValueChanged
})
]
});
}
});
As I understand it, I need a simple component to display the list, receiving it as a 'prop':
// A stateless component, displaying a list of item
var ItemList = return React.createClass({
propTypes : {
items : React.PropTypes.array
},
render : function () {
return React.DOM.ul({
children : _.map(this.props.items, function (item) {
return React.DOM.li({
children : [
React.DOM.span({
children : ["Name : ", item.name].join(" ")
})]
});
})
});
}
});
I tried this:
// A stateful react component, maintaining the list of items
var ItemPage = React.createClass({
getInitialState : function () {
// ?????
// This is where I'm sure the problem lies.
// How can this be known both on server and client side ?
return {
items : this.props.initialItems || []
};
},
queryItems : function (enteredName) {
var self = this;
// The field was emptied, we must clear everything
if (!enteredName) {
this.setState({
items : []
});
} else {
// The field was changed, we want to do a query
// then change the state to trigger a UI update.
// The query code is irrelevant, I think.
doQuery(enteredName).then(function (items) {
self.setState({
items : items
});
});
}
},
render : function () {
// I don't want to display the same view
// if there is no results.
// This uses a 'state' property of the page
var results = null;
if (_.isEmpty(this.state.items)) {
results = React.DOM.div({
ref : "results",
children : "No results"
});
} else {
results = ItemListView({
// Here items is a 'prop', the ItemList is technically
// stateless
items : this.state.items
});
}
return React.DOM.div({
children : [
ItemForm({
initialName : this.props.initialName,
onNameChanged : this.queryItems
}),
results
]
});
}
});
That's where I'm stuck. I can render things on the server side using something like:
var name = // The name from the query parameters
var items = doQueryOnServerSide(name);
React.renderComponentAsString(ItemPage({
initialName : name,
initialItems : items
});
But when I try to do write the client side javascript, what should I do ? I know where I want my dom to be rendered, but what initial props should I pass to the react component?
React.renderComponent(ItemPage({
initialName : ??? // Read the name parameter from URL ?
initialItems : ??? // I don't know yet, and I don't want to make an API call until the user entered something in the input box
});
Most attempts I have tried ends up with the DOM being 'erased' on the client-side, with this message:
React attempted to use reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server.
Note that only the markup of my ItemList component is erased, so I suppose it's an implementation problem of my component, but I don't really know where to start.
Am I on the right track? Or do I miss something entirely?
Yes! This is where server-side rendering for React comes in. In this article, I want to introduce you to server-side rending (SSR) with React, reasons to use it, and some popular frameworks for rendering React on the server side.
renderToString() Render a React element to its initial HTML. React will return an HTML string. You can use this method to generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes. If you call ReactDOM.
Does Facebook use Server Side Rendering? Yes, Facebook uses SSR heavily. However, according to Lee, there are very few areas where they use React to render components on server. This was primarily a decision based on their server environment which is Hack.
React along with other framework like angular and vue. js are traditional client side framework ,they run in browser but there are technology to run this framework on server side, and next. js is a solution for running react application server side.It also makes react development very simple.
When using server rendering, you should always pass down the same props that you used to render the component on the server. In this case, you need to pass down the same initialItems prop in order for React.renderComponent
to pick up the server-rendered markup (by simply JSONifying the props and putting it in the call to renderComponent
).
Your general structure of reading from initialItems when specified makes sense to me. Doing so allows you to either make a component with preloaded data or one that has none. What you need to set the initial state to depends on what you want to show in cases where you're rendering a brand-new component from scratch. (If you're always picking up server-rendered markup then you can simply always pass the initialName
and initialItems
props.)
Hope that makes sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With