不应用react-redux
创建一个store文件
- index.js 用来创建store和应用中间件等
import { createStore } from 'redux'
import reducer from './reducer.js'
// 创建store
const store = createStore(reducer)
export default store
- reducer.js用来创建reducer(state, action)函数,传给createStore创建store,
// 返回一个reducer函数,让createStore用来创建store
// 导入actionTypes.js中的type类型,方便我们进行识别操作
import {
A,
B
} from './actionTypes.js'
// state初始化
const defaultState = {
valueA: '',
valueB: ''
}
// 只能间接修改state
const reducer = (state = defaultState, action) => {
if (action.type === A) {
const newState = {...state}
newState.valueA = action.value
return newState
} else if (action.type === B) {
const newState = {...state}
newState.valueB = action.value
return newState
}
return state
}
export default reducer
- actionTypes.js 用来统一地方定义action对象的type类型,方便我们进行统一管理
// 用来定义action的类型,方便进行统一管理
export const A = 'A'
export const B = 'B'
- actionCreators.js 用于返回action对象
// 导入actionTypes.js中的type类型,方便我们进行识别操作
import {
A,
B
} from './actionTypes'
// 以函数的形式获取返回值,为action对象,其中action对象必须包含type属性,方便我们进行识别操作
export const setActionA = (value) => {
return {
type: A,
value
}
}
export const setActionB = (value) => {
return {
type: B,
value
}
}
- ReduxExample组件中使用
import React from 'react'
// 导入store
import store from './../../store'
// 导入action
import {
setActionA
} from './../../store/actionCreators'
class ReduxExample extends React.Component {
constructor(props) {
super(props)
this.state = store.getState()
// 监听store中的数据变化执行subscribe
this.handleStoreChange = this.handleStoreChange.bind(this)
store.subscribe(this.handleStoreChange);
}
render() {
return (
<div>
<h2>redux-example</h2>
<div>
{this.state.valueA}
</div>
</div>
)
}
componentDidMount() {
console.log(store.getState())
const actionA = setActionA('A')
setTimeout(() => {
store.dispatch(actionA) // dispatch修改state,从而触发store.subscribe重新执行
console.log(this.state)
console.log(store.getState())
}, 1000)
}
handleStoreChange() {
this.setState(store.getState())
}
}
export default ReduxExample
使用Chrome的Redux DevTools插件,方便我们进行开发
// store/index.js
import { createStore, compose } from 'redux'
import reducer from './reducer'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
// 创建store
const store = createStore(reducer, composeEnhancers())
export default store
应用react-redux
- 安装
- 使用 参考文档
// App.js 组件
import './App.css';
import ReduxExample from './pages/reduxtest/Test'
import { Provider } from 'react-redux'
import store from './store'
function App() {
return (
<Provider store={store}>
<ReduxExample/>
</Provider>
);
}
export default App;
// ReduxExample组件
import React from 'react'
// 导入action
import {
setActionA
} from './../../store/actionCreators'
import { connect } from 'react-redux'
class ReduxExample extends React.Component {
constructor(props) {
super(props)
this.state = {
name: 'test'
}
}
render() {
const { valueA, changeValueA } = this.props
return (
<div>
<h2>redux-example</h2>
{
valueA
}
<button onClick={changeValueA}>change</button>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
valueA: state.valueA,
valueB: state.valueB
}
}
const mapDispatchToProps = (dispatch) => {
return {
changeValueA: () => {
dispatch(setActionA('A'))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ReduxExample)
Immutable.js 对象来管理 store 中的数据
- 作用:保证state不被修改
- 参考文档
- 安装
npm install immutable或者yarn add immutable - 主要是通过formJS将JS对象转化为immutable对象,然后通过immutable提供的set和get方法进行操作数据
// store/reducer.js
// 返回一个reducer函数,让createStore用来创建store
// 导入actionTypes.js中的type类型,方便我们进行识别操作
import {
A,
B
} from './actionTypes.js'
// formJS将JS对象转化为immutable对象
import { fromJS } from 'immutable'
const defaultState = fromJS({
valueA: '',
valueB: ''
})
// state初始化
// const defaultState = {
// valueA: '',
// valueB: ''
// }
// 只能间接修改state
const reducer = (state = defaultState, action) => {
if (action.type === A) {
return state.set('valueA', action.value)
} else if (action.type === B) {
return state.set('valueB', action.value)
}
return state
}
export default reducer
// ReduxExample组件
import React from 'react'
// 导入action
import {
setActionA,
setActionB
} from './../../store/actionCreators'
import { connect } from 'react-redux'
class ReduxExample extends React.Component {
constructor(props) {
super(props)
this.state = {
name: 'test'
}
}
render() {
const { valueA, changeValueA } = this.props
return (
<div>
<h2>redux-example</h2>
{
valueA
}
<button onClick={changeValueA}>change</button>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
valueA: state.get('valueA'),
valueB: state.get('valueB')
}
}
const mapDispatchToProps = (dispatch) => {
return {
changeValueA: () => {
dispatch(setActionA('A'))
dispatch(setActionB('B'))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ReduxExample)
使用redux-thunk插件进行异步操作
dispatch一个action之后,到达reducer之前,进行一些额外的操作,就需要用到middleware。你可以利用 Redux middleware 来进行日志记录、创建崩溃报告、调用异步接口或者路由等等。 换言之,中间件都是对store.dispatch()的增强
- redux-thunk中将异步请求放到 actionCreators 里面
- redux-thunk 中间件实际上是对 dispatch 进行了处理而已,原本只能返回对象,现在能返回函数,当 dispatch 的实参是函数时就会自动执行.
- 安装
npm install redux-thunk或者yarn add redux-thunk - 使用
// store/index.js
import { createStore, compose, applyMiddleware } from 'redux'
import reducer from './reducer'
import thunk from 'redux-thunk'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
// 创建store
const store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)))
export default store
// store/actionCreators.js
// 导入actionTypes.js中的type类型,方便我们进行识别操作
import {
A,
B
} from './actionTypes'
// 返回一个异步的函数,一秒后进行操作
const waitRun = (val) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(val)
}, 1000)
})
}
// 以函数的形式获取返回值,为action对象,其中action对象必须包含type属性,方便我们进行识别操作
const setActionA = (value) => {
return {
type: A,
value
}
}
export const setActionB = (value) => {
return {
type: B,
value
}
}
export const waitOneSeconds = (val) => {
return (dispatch) => {
waitRun(val).then(res => {
const action = setActionA(res)
dispatch(action)
})
}
}
// ReduxExample组件
import React from 'react'
// 导入action
import {
waitOneSeconds
} from './../../store/actionCreators'
import { connect } from 'react-redux'
class ReduxExample extends React.Component {
constructor(props) {
super(props)
this.state = {
name: 'test'
}
}
render() {
const { valueA, changeValueA } = this.props
return (
<div>
<h2>redux-example</h2>
{
valueA
}
<button onClick={changeValueA}>change</button>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
valueA: state.get('valueA'),
valueB: state.get('valueB')
}
}
const mapDispatchToProps = (dispatch) => {
return {
changeValueA: () => {
dispatch(waitOneSeconds('A'))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ReduxExample)
使用redux-saga进行异步操作
此处只进行基本用法介绍,自己也还在继续深入学习
- Redux-saga 和 Redux-thunk 一样也是用来处理异步操作的,只是 Redux-saga 能独立出一个单独文件来写 api
- 安装
npm install redux-saga或者yarn add redux-saga