从0搭建react框架项目之redux配置
src/modle/index.js
import React, { Component } from 'react';
import { connect } from "react-redux";
import { bindActionCreators } from 'redux';
import store from "./../../store";
import {
action,
} from './reducer.js'
class Index extends Component {
constructor(props) {
super(props);
this.state = store.getState();
}
render() {
const {
action: {
add_list,
change_input,
},
index: {
inputValue,
list,
},
} = this.props
return (
<div>
<div>
<input type="text" style={{ height: '17px' }}
value={inputValue}
onChange={e => change_input(e.target.value)} />
{/* action(add_list) 可直接用add_list() */}
<button style={{ verticalAlign: 'middle' }} onClick={() => add_list()}>添加</button>
</div>
<div>
<ul>
{list.map((item, index) => {
return (<li key={item + index}>{item}</li>);
})}
</ul>
</div>
</div>
);
}
}
export default connect(
state => ({
index: state.index,
}),
dispatch => ({
action: bindActionCreators(action, dispatch),
})
)(Index)
首先创建一个Index组件,举了个小荔枝,大致效果如下图。
其中输入框的值inputValue、列表list这两个数据是存放在key为index的reducer中的。
组件要想拿到state中的数据,需要在最外层的容器中把所有内容裹在Provider组件中,然后将之前创建的store作为prop传给Provider。
//src/index.js
const App = () => {
return (
<Provider store={store}>
<Comp/>
</Provider>
)
};
Provider组件内的任何一个组件,(比如这里的index组件),如果需要使用state中的数据,就必须是被connect过后的组件。 connect(mapStateToProps, mapDispatchToProps, mergeProps, options)它接收四个参数,通常我们只用到前面两个,想深入了解的朋友可以去官网look look。connect的第一个参数mapStateToProps函数,这个函数允许我们把state中的数据作为props绑定到组件上。 因为我们组件用到的只有state.index中的数据所以我们只需要输出组件需要的index的数据。
const mapStateToProps = (state) => {
return {
index: state.index,
}
}
connect的第二个参数是mapDispatchToProps,这个函数是将action作为props绑定到index组件上。
const mapDispatchToProps = dispatch => ({
action: bindActionCreators(action, dispatch),
})
本质上要触发action就必须在store上调用dispatch方法,但是为了不让index组件感知到dispatch的存在,该方法已经过包装,即调用该方法就会触发dispatch,如上述调用add_list这个action时 可直接用add_list()。 bindActionCreators函数可以自动把多个action创建函数绑定到dispatch()方法上。上述我们通过import {action} from './reducer.js' 把reducer.js中的change_input和add_list两个action同时绑定到dispatch()上。
src/module/index/reducer.js
import {
handleActions,
createAction,
} from 'redux-actions'
const init_state = {
inputValue: '',
list: [
'睁眼起床',
'下床刷牙',
'穿衣出门',
],
}
const index_setter = createAction('index_setter')
// 隐射关系把原来的state映射成组件中的props属性
export const action = {
change_input: payload => (dispatch, get_state) => {
dispatch(
index_setter({
inputValue: payload,
})
)
},
add_list: payload => (dispatch, get_state) => {
const state = get_state()
const module_state = state['index']
let list = module_state.list
list.push(module_state.inputValue)
dispatch(
index_setter({
list: list,
inputValue: '',
})
)
}
}
export default handleActions({
[index_setter]: (state, { payload }) => ({
...state,
...payload,
}),
}, init_state)
使用createAction创建一个index
src/reducer.js
import {
combineReducers,
} from 'redux'
import index from './module/index/reducer'
import second from './module/second/reducer'
const app_reducer = combineReducers({ //整合所有的reducer
index,
second, //本次例子中没有提到,如果是直接复制过去报错,就注释掉这个reducer呀。
})
const rootReducer = (state, action) => {
return app_reducer(state, action)
}
export default rootReducer
src/store.js
import {
createStore,
applyMiddleware,
} from 'redux'
import rootReducer from './reducer.js'; // 相当于仓库管理员
import thunk from 'redux-thunk'
import logger from 'redux-logger'
const env = 'development' // development production //测试环境
let enhancer
if (env === 'production') {
enhancer = applyMiddleware(thunk)
} else {
enhancer = applyMiddleware(thunk, logger)
}
const store = createStore(rootReducer,{}, enhancer) //创建一个store
export default store
src/router.js 配置路由
import React, {
Component,
} from 'react'
import {
HashRouter,
Route,
Redirect,
} from 'react-router-dom'
import loadable from 'react-loadable'
// import Index from './module/index'
import Second from './module/second'
const Index = loadable({
loader: () => import('./module/index'),
loading() {
return <div>正在加载</div>
},
})
class Router extends Component {
render() {
return (
<HashRouter>
<Route exact path='/' render={() => <Redirect to='/home'/>}/>
<Route path='/home' component={Index}/>
<Route path='/second' component={Second}/>
</HashRouter>
)
}
}
export default Router
src/index.js 项目入口文件
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from "react-redux"; // 引入Provider组件
import store from "./store";
import Root from './router'
ReactDOM.render(
<Provider store={store}>
<Root />
</Provider>,
document.getElementById('root')
)