(精华)2020年7月31日 React 手写ssr服务端渲染
【摘要】
共用部分
import React ,{useState} from 'react'
import {connect} from 'react-redux'
import {getIndexList} ...
共用部分
import React ,{useState} from 'react'
import {connect} from 'react-redux'
import {getIndexList} from '../store/index'
const Index = (props) => {
let [count,setCount] = useState(1)
return (
<div>
<h1>服务端渲染</h1>
<h1>{count}</h1>
<button onClick={()=>{props.getIndexList()}}>加载</button>
<button onClick={()=>{setCount(count+1)}}>增加</button>
{
props.list.map(item=><li key={item.id}>{item.name}</li>)
}
</div>
)
}
Index.load = (store) => {
return store.dispatch(getIndexList())
}
export default connect(
state => ({list:state.index.list}),
{getIndexList}
)(Index)
import axios from 'axios'
const GET_LIST = 'INDEX/GET_LIST'
// action
const changeList = list => ({
type:GET_LIST,
list
})
// 有一个请求 可以改变reducer
export const getIndexList = ()=>{
return (dispatch)=>{
return axios.get('http://xxxxxxxxxxx').then((res)=>{
const {list} = res.data
dispatch(changeList(list))
})
}
}
const initState = {
list:[]
}
export default (state = initState,action) => {
switch(action.type){
case GET_LIST:
const newState = {
...state,
list:action.list
}
return newState
default:
return state
}
}
客户端
import React from 'react'
import ReactDOM from 'react-dom'
import {BrowserRouter} from 'react-router-dom'
import {Provider} from 'react-redux'
import {getClientStore} from '../store/store'
import {Route,Link} from 'react-router-dom'
import routers from '../router'
const store = getClientStore()
const App = ()=>{
return (
<Provider store={store}>
<BrowserRouter>
<div>
<Link to="/">首页</Link>
<Link to="/login">登录</Link>
</div>
{routers.map(route=><Route {...route}/>)}
</BrowserRouter>
</Provider>
)
}
ReactDOM.hydrate(
<App/>
,document.getElementById('root'))
服务端
import express from 'express'
import React from 'react'
import {renderToString} from 'react-dom/server' // 专门在server端使用的
import {StaticRouter} from 'react-router-dom'
import {Provider} from 'react-redux'
import {getStore} from '../store/store'
import {Route,Link} from 'react-router-dom'
import {matchRoutes} from 'react-router-config'
import routers from '../router'
let store = getStore()
let app = express()
app.use(express.static('public'))
app.get('*',function(req,res){
// 遍历所有的路由 寻找有load方法的
const matchedRoutes = matchRoutes(routers,req.path)
let promises = []
matchedRoutes.forEach(item=>{
let {load} = item.route.component
if(load){
const promise = new Promise((resolve,reject)=>{
load(store).then(resolve).catch(reject)
})
promises.push(promise)
}
})
Promise.all(promises).then(()=>{
let content = renderToString(
<Provider store={store}>
<StaticRouter>
<div>
<Link to="/">首页</Link>
<Link to="/login">登录</Link>
</div>
{routers.map(route=><Route {...route}/>)}
</StaticRouter>
</Provider>
)
const html = `
<html>
<head>
<title>软谋教育</title>
</head>
<body>
<div id="root">${content}</div>
<script>
window._context = ${JSON.stringify(store.getState())}
</script>
<script src="/main.js"></script>
</body>
</html>
`
res.send(html)
})
})
app.listen(1000,()=>{console.log('监听1000端口成功');
})
先编译客户端在启动服务端
"scripts": {
"dev:server": "webpack --config webpack.server.js --watch",
"dev:start": "nodemon --watch build --exec node \"./build/bundle.js\"",
"dev:client": "webpack --config webpack.client.js --watch"
},
文章来源: codeboy.blog.csdn.net,作者:愚公搬代码,版权归原作者所有,如需转载,请联系作者。
原文链接:codeboy.blog.csdn.net/article/details/107723690
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)