[英]Warning: Did not expect server HTML to contain a <li> in <ul>. in React/Redux Server side Rendering
我第一次使用 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);
这是 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')
);
问题是因为服务器已经呈现了用户列表,所以它有一个带有li
的ul
。 但是当客户端加载时没有初始数据,所以只有一个ul
而没有li
s伴随它。
要解决这个问题,我认为没有多少人会遇到这个问题,因为无论如何在服务器端渲染中都需要这样做是将一些初始状态传递给createStore
redux 函数:
您需要在两个地方执行此操作。 在服务器端的 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>
如您所见,我们必须将初始状态设置为您在服务器端创建的商店。
在您的客户端:
// 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')
);
现在您可以访问这个全局变量window.INITIAL_STATE
并且您只需将它传递给createStore
的第二个参数,即初始状态。
我现在在这里发帖是因为我正在使用 nextJS SSG 搜索这个确切的问题。 就像 Dave Newton 提到的那样,在 jsx 返回中,我会简单地添加一个检查,如果<ul>
由于对<li>
的条件检查而为空,则不会渲染它。 像这样的东西:
{Object.keys(el[i]).length > 0 ?
<ul>
{getKeys(docs, item, el).map(
([key, value], i) => {
const name = `${docs[item][el][key].name}`
const path = `${docs[item][el][key].path}`
return (name !== "undefined") && (
<li key={i}><a href={path}>{name}</a></li>
)}
)}
</ul>
: ''
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.