Redux应用单一的store原则案例详解
Redux应用单一的store原则案例详解
在开发reac单页面应用的时候,页面的展示逻辑跟数据状态的关系管理变得越来越复杂,redux很好的解决这个问题。废话不多说,直接先上官网api链接。
- http://cn.redux.js.org/index.html
官方文档跟你把概念性的东西讲解的很清楚的,怎么串联起来使用,就得多采坑才行。下面就是我踩的一个坑。 react-redux非组件里面store.dispatch(action)页面不更新的问题。主要是关于store的:
在前面的章节中,我们学会了使用 action 来描述“发生了什么”,和使用 reducers 来根据 action 更新 state 的用法。
Store 就是把它们联系到一起的对象。Store 有以下职责:
- 维持应用的 state;
- 提供
getState()
方法获取 state;- 提供
dispatch(action)
方法更新 state;- 通过
subscribe(listener)
注册监听器;- 通过
subscribe(listener)
返回的函数注销监听器。再次强调一下 Redux 应用只有一个单一的 store。当需要拆分数据处理逻辑时,你应该使用 reducer 组合而不是创建多个 store。
根据已有的 reducer 来创建 store 是非常容易的。在前一个章节中,我们使用
combineReducers()
将多个 reducer 合并成为一个。现在我们将其导入,并传递createStore()
。
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)
createStore()
的第二个参数是可选的, 用于设置 state 初始状态。这对开发同构应用时非常有用,服务器端 redux 应用的 state 结构可以与客户端保持一致, 那么客户端可以将从网络接收到的服务端 state 直接用于本地数据初始化。
let store = createStore(todoApp, window.STATE_FROM_SERVER)
- 1.问题如下:随便在一个js工具类里面获取store之后,再store.dispatch(actions),改变了状态后页面无法自动更新?只能在用页面组件connect自动注入到props里面的dispatch改变的状态才能自动更新页面?
- 2.代码如下
- Home 页面组件:
- class Home extends Component{
- constructor(props){
- super(props);
- this.goUser = this.goUser.bind(this)
- }
- goUser() {
- let {dispatch} = this.props;
- // 通过注入的dispatch对象调用就正常,能触发页面自动更新
- **dispatch(setDialogState({showDialog: true}));
- // 通过工具类就不行,状态改变后无法触发页面更新
- utils.setDialogState({showDialog: true});
- this.props.history.push('/user')
- }
- render() {
- return (
- <div>
- <h3>home</h3>
- <button onClick={this.goUser}>去用户中心页面</button>
- </div>
- )
- }
- }
- export default connect()(Home);
======utils.js文件如下:- import storeConfigure from '../store';
- import {setDialogState} from '../actions';
- const appStore = storeConfigure()
- export default {
- setDialogState: function(data){
- appStore.dispatch(setDialogState(data))
- }
- }
- user.js页面组件
- import React,{Component} from 'react';
- import Dialog from './Dialog';
- import { connect } from 'react-redux'
- class User extends Component{
- constructor(props){
- super(props);
- }
- componentWillMount() {
- alert('componentWillMount user')
- }
- componentWillReceiveProps(nextProps){
- alert('componentWillReceiveProps user')
- }
- render() {
- return (
- <div>
- <h3>user</h3>
- <Dialog show={this.props.showDialog}/>
- </div>
- )
- }
- }
- const mapStateToProps = function(state) {
- return {
- showDialog: state.app.showDialog
- }
- }
- export default connect(mapStateToProps)(User);
======reducers文件夹下的app分块的js内容如下- import * as types from '../actions/actionType'
- let initialState = {
- showDialog: false
- }
- export function app(state=initialState,action){
- switch(action.type){
- case types.SET_DIALOG_STATE:
- return Object.assign({},initialState,action.data);
- break;
- default :
- return Object.assign({},initialState,action.data);
- break;
- }
- }
- store.js如下:
- import {createStore} from 'redux';
- import reducers from '../reducers';
- export default function configureStore(initialState) {
- let store = createStore(reducers, initialState,
- // 触发 redux-devtools
- window.devToolsExtension ? window.devToolsExtension() : undefined
- );
- return store;
- }
====全局App.js入口文件
上面问题哪里不对了?。
问题就出在这里:
- configureStore()在你的react项目里,只能出现一次,记住只能出现一次!!!
如果出现了多次,就是违背了单一store原则。哪怕你状态也改了,页面就是不会自动更新,因为页面注入的状态来自于另一个store。
下面就是你的store的写法,推荐的写法跟不推荐的写法。
- import {createStore, applyMiddleware } from 'redux';
- import thunkMiddleware from 'redux-thunk'
- import { createLogger } from 'redux-logger'
- import reducers from '../reducers';
- const loggerMiddleware = createLogger()
- // 不推荐的写法
- export default function configureStore(initialState) {
- let store = createStore(reducers, initialState,
- applyMiddleware(thunkMiddleware, loggerMiddleware),
- // 触发 redux-devtools
- window.devToolsExtension ? window.devToolsExtension() : undefined
- );
- console.log(store)
- return store;
- }
- // 推荐的写法
- function configureStore(initialState) {
- let store = createStore(reducers, initialState,
- applyMiddleware(thunkMiddleware, loggerMiddleware),
- // 触发 redux-devtools
- window.devToolsExtension ? window.devToolsExtension() : undefined
- );
- console.log(store)
- return store;
- }
- const appStore = configureStore();
- export default appStore;
当然,这问题主要使用的场景就是在非react组件里面通过store.dispatch(action)来改变状态。
比如建立websocket的事件监听,或者一个普通uitls.js里面的。
有点类似于JavaScript原生的addEventListener。