内容简介:这一节主要是讲述Redux如何被引入到同构项目中以及其中需要注意的问题。重新回顾一下redux的运作流程:再回顾一下同构的概念,即在React代码客户端和服务器端各自运行一遍。
这一节主要是讲述Redux如何被引入到同构项目中以及其中需要注意的问题。
重新回顾一下redux的运作流程:
再回顾一下同构的概念,即在React代码客户端和服务器端各自运行一遍。
一、创建全局store
现在开始创建store。 在项目根目录的store文件夹(总的store)下:
import {createStore, applyMiddleware, combineReducers} from 'redux'; import thunk from 'redux-thunk'; import { reducer as homeReducer } from '../containers/Home/store'; //合并项目组件中store的reducer const reducer = combineReducers({ home: homeReducer }) //创建store,并引入中间件thunk进行异步操作的管理 const store = createStore(reducer, applyMiddleware(thunk)); //导出创建的store export default store 复制代码
二、组件内action和reducer的构建
Home文件夹下的工程文件结构如下:
在Home的store目录下的各个文件代码示例:
//constants.js export const CHANGE_LIST = 'HOME/CHANGE_LIST'; 复制代码
//actions.js import axios from 'axios'; import { CHANGE_LIST } from "./constants"; //普通action const changeList = list => ({ type: CHANGE_LIST, list }); //异步操作的action(采用thunk中间件) export const getHomeList = () => { return (dispatch) => { return axios.get('xxx') .then((res) => { const list = res.data.data; console.log(list) dispatch(changeList(list)) }); }; } 复制代码
//reducer.js import { CHANGE_LIST } from "./constants"; const defaultState = { name: 'sanyuan', list: [] } export default (state = defaultState, action) => { switch(action.type) { default: return state; } } 复制代码
//index.js import reducer from "./reducer"; //这么做是为了导出reducer让全局的store来进行合并 //那么在全局的store下的index.js中只需引入Home/store而不需要Home/store/reducer.js //因为脚手架会自动识别文件夹下的index文件 export {reducer} 复制代码
三、组件连接全局store
下面是Home组件的编写示例。
import React, { Component } from 'react'; import { connect } from 'react-redux'; import { getHomeList } from './store/actions' class Home extends Component { render() { const { list } = this.props return list.map(item => <div key={item.id}>{item.title}</div>) } } const mapStateToProps = state => ({ list: state.home.newsList, }) const mapDispatchToProps = dispatch => ({ getHomeList() { dispatch(getHomeList()); } }) //连接store export default connect(mapStateToProps, mapDispatchToProps)(Home); 复制代码
对于store的连接操作,在同构项目中分两个部分,一个是与客户端store的连接,另一部分是与服务端store的连接。都是通过react-redux中的Provider来传递store的。
客户端:
//src/client/index.js import React from 'react'; import ReactDom from 'react-dom'; import {BrowserRouter, Route} from 'react-router-dom'; import { Provider } from 'react-redux'; import store from '../store' import routes from '../routes.js' const App = () => { return ( <Provider store={store}> <BrowserRouter> {routes} </BrowserRouter> </Provider> ) } ReactDom.hydrate(<App />, document.getElementById('root')) 复制代码
服务端:
//src/server/index.js的内容保持不变 //下面是src/server/utils.js import Routes from '../Routes' import { renderToString } from 'react-dom/server'; import { StaticRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; import React from 'react' export const render = (req) => { const content = renderToString( <Provider store={store}> <StaticRouter location={req.path} > {Routes} </StaticRouter> </Provider> ); return ` <html> <head> <title>ssr</title> </head> <body> <div id="root">${content}</div> <script src="/index.js"></script> </body> </html> ` } 复制代码
四、潜在的坑
其实上面这样的store创建方式是存在问题的,什么原因呢?
上面的store是一个单例,当这个单例导出去后,所有的用户用的是同一份store,这是不应该的。那么这么解这个问题呢?
在全局的store/index.js下修改如下:
//导出部分修改 export default () => { return createStore(reducer, applyMiddleware(thunk)) } 复制代码
这样在客户端和服务端的js文件引入时其实引入了一个函数,把这个函数执行就会拿到一个新的store,这样就能保证每个用户访问时都是用的一份新的store。
以上所述就是小编给大家介绍的《React服务端渲染探秘:3.同构项目中引入Redux》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- React服务端渲染探秘:1.实现一个基础的React组件SSR、初识同构
- react同构实践——实现自己的同构模板
- 如何构建一个WEB同构应用
- React Native 三端同构实战
- React服务端渲染(前后端路由同构)
- React 中同构(SSR)原理脉络梳理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。