react服务端渲染-04

82 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情

上篇文章讲解了 服务度渲染中的前端注水

这篇文章讲解写reactStore

初始化 reactStore

使用 react-redux来管理状态

首先安装下redux

yarn add redux react-redux

在src目录下创建store文件夹

在store文件夹下创建index.js来管理store入口

在strore文件夹下创建 actions文件夹,actions文件夹下分别创建 home.js和 person.js来管理这两个的action

在store文件夹下创建reducers文件夹,在reducers文件夹下分别创建home.js和person.js来管理这两个的reducer

首先来写下action

// actions/home.js
export const FETCH_HOME_DATA = 'fetch_home_data';

export const fetchHomeData = async (dispatch) => {

    const  data = await new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({
                articles: [
                    {
                        id: 1,
                        title: 'title1',
                        content: 'content1'
                    },
                    {
                        id: 2,
                        title: 'title2',
                        content: 'content2'
                    }
                ]
            })
        },2000)
    })
    dispatch({
        type: FETCH_HOME_DATA,
        payload: data
    })
}
export const FETCH_PERSON_DATA = 'fetch_person_data';

export const fetchPersonData = async (dispatch) => {

    const  data = await new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({
                userInfo: {
                    username: 'curry',
                    job: '前端工程师'
                }
            })
        },2000)
    })
    dispatch({
        type: FETCH_PERSON_DATA,
        payload: data
    })
}

让开始写reducers

// reducers/home.js
import { FETCH_HOME_DATA } from '../actions/home';

const initState = {
    articles: []
}
export default (state = initState ,action) => {
    switch(action?.type){
        case FETCH_HOME_DATA:
             return action.payload;
        default:
            return state;
    }
}
// reducers/person.js
import { FETCH_PERSON_DATA } from '../actions/person';

const initState = {
    info: {}
}
export default (state = initState ,action) => {
    switch(action?.type){
        case FETCH_PERSON_DATA:
             return action.payload;
        default:
            return state;
    }
}

最后将这两个reducer合并起来

在 reducers/index.js中将两个合并

import { combineReducers } from 'redux'
import homeReducer from './home'
import personReducer from './person'


export default combineReducers({
    home: homeReducer,
    person: personReducer
})

最后在stroe中引入redux

import { createStore } from 'redux'
import reducer from './reducers'
const store = createStore(reducer)

export default store;

开始使用store

在client.js中使用store

在使用store的时候,需要使用到react-redux提供的Provider,相当于context中的provider,

将Provider包裹住,将store传入Provider,这样的话,才能在组件中接受到store

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux'
import Routes from './routes';
import store from './store'


ReactDOM.hydrate(
    <Provider store={store}>
        <BrowserRouter>
        <Routes />
        </BrowserRouter>
    </Provider>,
  document.querySelector('#root')
);

同时也需要在server.js中引入Provider,并将store传入Provider

import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { StaticRouter } from 'react-router-dom/server'
import { Provider } from 'react-redux'
import Routes from './routes'
import store from './store'

const express = require('express');


const app = express();


const port = process.env.port || 3000;


app.use(express.static('dist/public'))

app.get('*', (req, res) => {


    const content = ReactDOMServer.renderToString(
        <Provider store={store}>
        <StaticRouter location={req.url}>
            <Routes />
        </StaticRouter>
        </Provider>
    )

    const html = `
        <html>
            <head></head>
            <body>
                <div id="root">${content}</div>
                <script src="bundle_client.js"></script>
            </body>
        </html>
    `
    res.writeHead(200,{
        'content-type': 'text/html;charset=utf8'
    })
    res.end(html)
})

app.listen(port, () => {
    console.log('http://localhost:3000')
})