admin管理员组文章数量:1252688
I am doing Server Side Rendering for the first time with React and Redux and seeming to be having a little difficulty. 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. 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 {
ponentDidMount() {
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:
// 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')
);
I am doing Server Side Rendering for the first time with React and Redux and seeming to be having a little difficulty. 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. 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 {
ponentDidMount() {
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:
// 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')
);
Share
Improve this question
asked Oct 30, 2017 at 14:13
Taylor AustinTaylor Austin
6,00716 gold badges63 silver badges108 bronze badges
2
- According to stackoverflow./a/45371427/1427878 this sems to happen when “you are somehow initially rendering a different tree on the client vs the server” – C3roe Commented Oct 30, 2017 at 14:16
- 2 Yes but how do I fix it ? – Taylor Austin Commented Oct 30, 2017 at 14:17
2 Answers
Reset to default 8The problem was that since the server had rendered the list of users already, it had a ul
with li
s. But when the client loaded there was no initial data so there was only an ul
and no li
s to acpany it.
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:
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.
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.
I'm posting here now because I was searching this exact issue with 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. 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>
: ''
}
本文标签:
版权声明:本文标题:javascript - Warning: Did not expect server HTML to contain a <li> in <ul>. in ReactRedux Server sid 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1740311731a2259534.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论