[英]Warning: Did not expect server HTML to contain a <li> in <ul>. in React/Redux Server side Rendering
I am doing Server Side Rendering for the first time with React and Redux and seeming to be having a little difficulty.我第一次使用 React 和 Redux 进行服务器端渲染,似乎有点困难。 I am getting the warning:
我收到警告:
Warning: Did not expect server HTML to contain a <li> in <ul>.
I have looked this up and it means that there is a html tree mismatch.我查了一下,这意味着 html 树不匹配。 I am not sure how that is.
我不确定那是怎么回事。 Is there an obvious way to fix it?
有没有明显的方法来解决它? Here is the code I have that is throwing the warning.
这是我抛出警告的代码。
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);
Here is the client.js:这是 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')
);
The problem was that since the server had rendered the list of users already, it had a ul
with li
s.问题是因为服务器已经呈现了用户列表,所以它有一个带有
li
的ul
。 But when the client loaded there was no initial data so there was only an ul
and no li
s to accompany it.但是当客户端加载时没有初始数据,所以只有一个
ul
而没有li
s伴随它。
To fix this problem, which I think not many will have because you need to do this anyway in server side rendering is to pass some initial state into the createStore
redux function:要解决这个问题,我认为没有多少人会遇到这个问题,因为无论如何在服务器端渲染中都需要这样做是将一些初始状态传递给
createStore
redux 函数:
You will need to do this in two places.您需要在两个地方执行此操作。 In the html on your server side and in your entry point on the client side.
在服务器端的 html 和客户端的入口点中。
Short example could be:简短的例子可能是:
<html>
<head></head>
<body>
<div id="root">${content}</div>
<script>
window.INITIAL_STATE = ${serialize(store.getState())}
</script>
<script src="bundle.js"></script>
</body>
</html>
As you can see we have to set the initial state to the store that you created on your server side.如您所见,我们必须将初始状态设置为您在服务器端创建的商店。
On your client side:在您的客户端:
// 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')
);
Now you have access to this global variable window.INITIAL_STATE
and you just pass that through into the second argument of createStore
which is the initial state.现在您可以访问这个全局变量
window.INITIAL_STATE
并且您只需将它传递给createStore
的第二个参数,即初始状态。
I'm posting here now because I was searching this exact issue with nextJS SSG.我现在在这里发帖是因为我正在使用 nextJS SSG 搜索这个确切的问题。 Just like Dave Newton mentioned, in the jsx return I would simply add a check and not render the
<ul>
if it is empty due to a conditional check on the <li>
's.就像 Dave Newton 提到的那样,在 jsx 返回中,我会简单地添加一个检查,如果
<ul>
由于对<li>
的条件检查而为空,则不会渲染它。 Something like this:像这样的东西:
{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.