警告:不要指望服务器HTML在<ul>中包含<li>.在React/Redux Server端渲染

Tay*_*tin 6 javascript reactjs redux

我第一次使用React和Redux进行服务器端渲染,看起来有点困难.我收到警告:

Warning: Did not expect server HTML to contain a <li> in <ul>.

我看了这个,这意味着有一个html树不匹配.我不确定那是怎么回事.有没有明显的方法来解决它?这是我发出警告的代码.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import actions from '../actions';

class UsersList extends Component {
  componentDidMount() {
    if (this.props.users.length > 0) {
      return;
    }
    this.props.fetchUsers();
  }

  render() {
    const { users } = this.props;
    return (
      <div>
        <ul>
          {users.map(user => {
            return <li key={user.id}>{user.name}</li>;
          })}
        </ul>
      </div>
    );
  }
}

const stateToProps = state => {
  return {
    users: state.users
  };
};

const dispatchToProps = dispatch => {
  return {
    fetchUsers: () => dispatch(actions.fetchUsers())
  };
};

const loadData = store => {
  return store.dispatch(actions.fetchUsers());
};

export { loadData };
export default connect(stateToProps, dispatchToProps)(UsersList);
Run Code Online (Sandbox Code Playgroud)

这是client.js:

// Startup point for the client side application
import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';

import Routes from './Routes';
import reducers from './reducers';

const store = createStore(reducers, {}, applyMiddleware(thunk));

ReactDOM.hydrate(
  <Provider store={store}>
    <BrowserRouter>
      <div>{renderRoutes(Routes)}</div>
    </BrowserRouter>
  </Provider>,
  document.querySelector('#root')
);
Run Code Online (Sandbox Code Playgroud)

Tay*_*tin 5

问题在于,由于服务器已经呈现了用户列表,因此它具有一个ul带有li的。但是,当客户端加载时,没有初始数据,因此只有ul,没有lis陪伴。

为了解决这个问题,我认为这个问题并不多,因为无论如何在服务器端渲染中都需要这样做,就是将一些初始状态传递给createStoreredux函数:

您将需要在两个地方执行此操作。在服务器端的html中和客户端的入口点中。

简短的示例可能是:

<html>
  <head></head>
  <body>
    <div id="root">${content}</div>
    <script>
      window.INITIAL_STATE = ${serialize(store.getState())}
    </script>
    <script src="bundle.js"></script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

如您所见,我们必须将初始状态设置为您在服务器端创建的商店。

在您的客户端上:

// Startup point for the client side application
import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';

import Routes from './Routes';
import reducers from './reducers';

const store = createStore(reducers, window.INITIAL_STATE, applyMiddleware(thunk));

ReactDOM.hydrate(
  <Provider store={store}>
    <BrowserRouter>
      <div>{renderRoutes(Routes)}</div>
    </BrowserRouter>
  </Provider>,
  document.querySelector('#root')
);
Run Code Online (Sandbox Code Playgroud)

现在,您可以访问此全局变量window.INITIAL_STATE,只需将其传递给第二个参数createStore即初始状态即可。

  • 我可能已经通过不呈现空列表来修复它。 (2认同)