简体   繁体   中英

Isomorphic React App markup reuse error

I'm building a very simple isomorphic React/Redux app and in one of my containers I want to load a user's details and a list of their albums.

Everything works okay both server and client side but I get the error:

Warning: React attempted to 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:
 (client) iv data-reactid="2">Loading...</div></di
 (server) iv data-reactid="2"><a href="/users" dat

I understand that this is because on load the server and client may be different because the client takes longer to fetch the data. However how to I get around this issue?

If I remove the {!user} return, then the page doesn't render and I get an error message saying that {user.firstName} does not exist.

Here's my component code:

// IMPORT DEPENDENCIES
// ==============================================

import React, {Component, PropTypes} from 'react';
import {Link} from 'react-router';
import {connect} from 'react-redux';
import {getAlbumsByUserId} from '../../redux/album/albumActions';
import {getUser} from '../../redux/user/userActions';

// USER CONTAINER
// ==============================================

export class User extends Component {

static propTypes = {
    getAlbumsByUserId: PropTypes.func,
    getUser: PropTypes.func,
    params: PropTypes.object,
    user: PropTypes.object
};

static needs = [
    getAlbumsByUserId,
    getUser
];

componentWillMount () {
    this.props.getAlbumsByUserId();
    this.props.getUser();
}

render () {
    const {albums, user} = this.props;

    if (!user) {
        return <div>Loading...</div>;
    }

    return (
        <div>
            <Link to='/users'>Back to users</Link>
            <h1>User: {user.firstName} {user.lastName}</h1>

            {albums &&
                albums.map((album) =>
                    <div key={album.id}>
                        <h2>
                            <Link to={`/albums/${album.id}`}>
                                {album.title}
                            </Link>
                        </h2>
                    </div>
                )
            }
        </div>
    );
}
}





// MAPPINGS
// ==============================================

const mapStateToProps = ({albums, users}) => {
    return {
        albums: albums.list.items,
        user: users.activeItem.item
    };
};

const mapDispatchToProps = (dispatch, props) => {
    return {
        getAlbumsByUserId: () => { dispatch   (getAlbumsByUserId(props.params)); },
        getUser: () => { dispatch(getUser(props.params)); }
    };
};





// EXPORT
// ==============================================

export default connect(mapStateToProps, mapDispatchToProps)(User);

the static needs tells the server which actions it requires on page load.

看来我需要使用ComponentDidMount而不是ComponentWillMount

Usually, when dealing with isomorphic way we pass the inital data from server along with index file rather then loading the data using ajax. eg in our main HTML file we'll have something like

<script>
  var APP_PROPS = JSON.stringify(props);
</script>

and use this data for initial rendering.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM