Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Server side rendering React components that loads state through Ajax

I'm struggling to make my component work on both client and server side.

This is the code for my component:

export default class extends React.Component {
    constructor(props, context) {
        super(props, context);

        this.state = {
            title: props.params.title,
            message: props.params.message
        };
    }

    componentDidMount() {
        $.ajax({
            url: "/get-message",
            success: function (result) {
                this.setState({
                    title: result.title,
                    message: result.message
                });
            }.bind(this),
            cache: false
        });
    }

    render() {
        return (
            <div>
                <h2>{this.state.title}</h2>
                <h3>{this.state.message}</h3>
            </div>
        );
    }
}

It works ok. When it gets rendered though client side, it shows both h2 and h3 empty and then they are filled when the ajax call returns.

When it gets rendered though the server, I already get those props filled and the html sent to the client is already completed and don't need anything extra.

The problem is that when it gets rendered on the server, I get the error message on the client:

Warning: React attempted to reuse markup in a container but the checksum was invalid. [...]

It then calls the ajax method again and re-renders everything.

So how should I handle such case? Is there a way to tell React that this component was rendered on the server accept it and not call the componentDidMount method?

like image 451
user3900456 Avatar asked Apr 12 '26 17:04

user3900456


1 Answers

A common way to work with this is by using global state. You could serialize a JS object at the bottom of the <body> tag, containing the state calculated on the server side.

<script>globalState={MyFeature: {title: 'foo'}};</script>

Then use that state (or a branch of it) as default for your components.

e.g.

if (globalState.MyFeature.title) {
    this.setState({ title: globalState.MyFeature.title });
} else {
    $.ajax(/* ... */);
}

Obviously you can use Redux to manage your global state nicely, but you don't really need to. However, there are many useful packages available that will help you streamline this process.

  • react router redux
  • redux-async-connect
  • serialize-javascript - you can use this one without redux
like image 190
Grgur Avatar answered Apr 15 '26 07:04

Grgur



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!