Redux基础知识
redux是一个专注于状态管理的库。redux不仅仅可以在react框架中使用,也可以在其他框架中使用。
状态少的时候,可以用setState来管理,但是状态越来越庞大,复杂时,就需要用到redux管理状态了
安装redux
npm install redux --save
最基本的使用redux
import {createStore} from 'redux'
//新建store,根据老的state和action,生成新的state
function counter( state = 0, action ){
switch(action.type){
case "加":
return state + 1;
case "减":
return state - 1;
default:
return state = 10
}
}
const store = createStore(counter)
const init = store.getState()
console.log(init)
store.dispatch({type:"加"})
console.log(store.getState());
store.dispatch({type:"减"})
console.log(store.getState());
输出情况:
10
11
10
已经实现了对state的操作。
实现状态实时打印,不用手动输出:
......
function listener(){
const init = store.getState()
console.log(`现在state等于${init}`)
}
store.subscribe(listener)
store.dispatch({type:'加'})
store.dispatch({type:'加'})
store.dispatch({type:'加'})
store.dispatch({type:'加'})
打印结果
现在state等于11
现在state等于12
现在state等于13
现在state等于14
如何把redux和react配合使用
- 把store.dispacth方法传递给组件,内部可以调用修改状态
- subscribe订阅render函数,一旦状态发生改变重新渲染页面
- redux相关内容,移动到单独文件index.redux.js管理(或者独立成文件夹)
例如:
在src目录新建index.redux.js,在这里,先不分成state,action。reducer独立文件
const ADD = "加"
const REM = "减"
export function counter( state = 0, action ){
switch(action.type){
case ADD:
return state + 1;
case REM:
return state - 1;
default:
return state = 10
}
//action
//action creator
export function addGUN(){
return {type:ADD}
}
export function remGUN(){
return {type:REM}
}
在index.js挂在App组件,导入state
import React from 'react'
import ReactDom from 'react-dom'
import {createStore} from 'redux'
import {counter} from "./index.redux"
import App from './App'
const store = createStore(counter)
//新建store,根据老的state和action,生成新的state
function render(){
ReactDom.render(
<App store={store}/>,document.getElementById("root")
)
}
render()
store.subscribe(render)//状态变化则更新render,重新渲染
在App组件中,对传入的state进行操作
import React from "react"
import { addGUN, remGUN} from './index.redux'
class App extends React.Component{
render(){
//console.log(this.props.store)
const state = this.props.store
return <div>
<h1>{state.getState()}</h1>
<button onClick={() => state.dispatch(addGUN())}>加</button>
<button onClick={() => state.dispatch(remGUN())}>减</button>
</div>
}
}
export default App
可以在页面点击button改变state的状态了
使用Redux处理异步
Redux处理异步,需要用到redux-thunk。
redux默认只处理同步,异步需要react-thunk中间键
- npm redux-thunk --save
- 使用apliyMiddware开启thunk中间件
- action可以返回函数,使用dispacht提交action
在index.js引入redux-thunk,在创建store函数中添加代码
......
import thunk from 'redux-thunk'
const store = createStore(counter,applyMiddleware(thunk))
在index.redux.js文件中编写一个异步函数。如延迟两秒加一
export function addGunAsync(){
return dispatch => {
setTimeout(() => {
dispatch(addGUN())
},2000)
}
}
在App.js中添加按钮出发函数
render(){
console.log(this.props.store)
const state = this.props.store
return <div>
<h1>{state.getState()}</h1>
<button onClick={() => state.dispatch(addGUN())}>加</button>
<button onClick={() => state.dispatch(remGUN())}>减</button>
<button onClick={() => state.dispatch(addGunAsync())}>加</button>
</div>
}
但是,这样的操作有点繁琐,所以使用react-redux
npm i react-redux --save
render函数这样写
......
import {provider} from 'react-redux'
function render(){
ReactDom.render(
(<Provider store={store}>
<App />
</Provider>),
document.getElementById("root")
)
}
只需要传一个props,App.js中的render则可以改写成`
......
import { connect } from 'react-redux'
......
render(){
console.log(this.props)
const num = this.props.num
const addGUN = this.props.addGUN
const remGUN = this.props.remGUN
const addGunAsync = this.props.addGunAsync
return <div>
<h1>{num}</h1>
<button onClick={addGUN}>加</button>
<button onClick={remGUN}>减</button>
<button onClick={addGunAsync}>加</button>
</div>
}
const mapStatetoProp = (state) => {
return {num:state}
}
const actionCreactors = { addGUN, remGUN,addGunAsync}
App = connect(mapStatetoProp,actionCreactors)(App)
export default App