- redux的核心api
- createStore()
- 创建包含指定reducer的store对象
- store对象
- redux库最核心的管理对象
- 内部维护着 state reducer对象
- 核心方法
- getState()
- dispatch(action)
- subscribe
- redux的三个核心概念
- action
- 标识要执行行为的对象
- 包含两个方面的属性
- type 标识属性 值是字符串 唯一 必要的属性
- xxx 数据属性 值类型是任意的 可选属性
- const action = {type:‘add’,data:2}
- action的创建工厂
const add = ()=>({type:‘add’,data:123})- reducer
- 根据老的state 返回新的state 纯函数
- 编码见代码
- 注意
- 返回一个新的状态
- 不要修改原来的状态
- store
- 将state action reducer 联系在一起的对象
- 如何得到这个对象? 见代码
- 得到这个对象的功能是什么
- getState() 得到state
- dispatch(action) 分发action 触发reducer的调用 产生新的state
- subscribe() 注册监听 当产生了新的state之后 会自动的调用
首先定义函数变量action-type.js
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
action.js
import {INCREMENT,DECREMENT} from './action-type'
export const increment = number => ({type:INCREMENT,number})
export const decrement = number => ({type:DECREMENT,number})
reducers.js
import {INCREMENT,DECREMENT} from './action-type'
export function counter(state=0,action){
switch(action.type){
case INCREMENT:
return state + action.number
case DECREMENT:
return state - action.number
default:
return state
}
}
combineReducers可以连接多个
import {combineReducers} from 'redux'
import {
ADD_COMMENT,
DELETE_COMMENT,
RECEIVE_COMMENT
} from './action-types'
//
const initComments = []
function comments(state=initComments,action){
switch(action.type){
case ADD_COMMENT:
return [...state,action.data]
case DELETE_COMMENT:
return state.filter((c,index)=>index !== action.data)
case RECEIVE_COMMENT:
return action.data
default :
return state
}
}
export default combineReducers({
comments
})
redux下index.js中引用
import React from 'react'
import ReactDOM from 'react-dom'
import {createStore} from 'redux'
import App from './components/app'
import {counter} from './redux/reducers'
const common = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__//安装谷歌插件在浏览器调试
const store = createStore(counter,common())
const render = ()=>{
ReactDOM.render(<App store={store}/>, document.getElementById('root'))
}
// 初始化渲染
render()
// 注册监听
store.subscribe(render)
redux页面中使用
import React, {Component} from 'react'
import * as actions from '../redux/actions'
export default class App extends Component {
state = {
count: 0
}
increment = () => {
const num = this.refs.numSelect.value*1
this.props.store.dispatch(actions.increment(num))
}
decrement = () => {
const num = this.refs.numSelect.value*1
this.props.store.dispatch(actions.decrement(num))
}
incrementIfOdd = () => {
let count = this.state.count
if(count%2==1) {
this.props.store.dispatch(actions.increment(count))
}
}
incrementAsync = () => {
const num = this.refs.numSelect.value*1
setTimeout(() => {
this.props.store.dispatch(actions.increment(num))
}, 1000)
}
render () {
return (
<div>
<p>
click {this.props.store.getState()} times {' '}
</p>
<select ref="numSelect">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>{' '}
<button onClick={this.increment}>+</button>{' '}
<button onClick={this.decrement}>-</button>{' '}
<button onClick={this.incrementIfOdd}>increment if odd</button>{' '}
<button onClick={this.incrementAsync}>increment async</button>
</div>
)
}
}
下面介绍react-redux的使用
app.js
import React, {Component} from 'react'
import {connect} from 'react-redux'
import Counter from '../components/counter'
import {increment,decrement} from '../redux/actions'
export default connect(
state=>({count:state}),
{
increment,
decrement
}
)(Counter)
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import {createStore} from 'redux'
import {Provider} from 'react-redux'
import App from './container/app.js'
import {counter} from './redux/reducers'
import {composeWithDevTools} from 'redux-devtools-extension'
// const common = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
const store = createStore(counter,composeWithDevTools())
ReactDOM.render(<Provider store={store}>
<App />
</Provider>, document.getElementById('root'))
页面中使用
import React, {Component} from 'react'
export default class Counter extends Component {
increment = () => {
const num = this.refs.numSelect.value*1
this.props.increment(num)
}
decrement = () => {
const num = this.refs.numSelect.value*1
this.props.decrement(num)
}
incrementIfOdd = () => {
const num = this.refs.numSelect.value*1
let count = this.props.count
if(count%2==1) {
this.props.increment(num)
}
}
incrementAsync = () => {
const num = this.refs.numSelect.value*1
setTimeout(() => {
this.props.increment(num)
}, 1000)
}
render () {
return (
<div>
<p>
click {this.props.count} times {' '}
</p>
<select ref="numSelect">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>{' '}
<button onClick={this.increment}>+</button>{' '}
<button onClick={this.decrement}>-</button>{' '}
<button onClick={this.incrementIfOdd}>increment if odd</button>{' '}
<button onClick={this.incrementAsync}>increment async</button>
</div>
)
}
}
redux的异步使用
改写上面的action.js
import {INCREMENT,DECREMENT} from './action-type'
export const increment = number => ({type:INCREMENT,number})
export const decrement = number => ({type:DECREMENT,number})
//异步用法
export const incrementAsync = number => {
return dispatch =>{
setTimeout(()=>{
dispatch(increment(number))
},2000)
}
}
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import {createStore,applyMiddleware} from 'redux'
import {Provider} from 'react-redux'
import App from './container/app.js'
import {counter} from './redux/reducers'
import {composeWithDevTools} from 'redux-devtools-extension'
import thunk from 'redux-thunk'//异步
// const common = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
const store = createStore(
counter,
composeWithDevTools(applyMiddleware(thunk))//加上中间件配合异步
)
ReactDOM.render(<Provider store={store}>
<App />
</Provider>, document.getElementById('root'))
app.js
import React, {Component} from 'react'
import {connect} from 'react-redux'
import Counter from '../components/counter'
import {increment,decrement,incrementAsync} from '../redux/actions'
export default connect(
state=>({count:state}),
{
increment,
decrement,
incrementAsync
}
)(Counter)
页面使用
import React, {Component} from 'react'
export default class Counter extends Component {
increment = () => {
const num = this.refs.numSelect.value*1
this.props.increment(num)
}
decrement = () => {
const num = this.refs.numSelect.value*1
this.props.decrement(num)
}
incrementIfOdd = () => {
const num = this.refs.numSelect.value*1
let count = this.props.count
if(count%2==1) {
this.props.increment(num)
}
}
incrementAsync = () => {
const num = this.refs.numSelect.value*1
this.props.incrementAsync(num)
}
render () {
return (
<div>
<p>
click {this.props.count} times {' '}
</p>
<select ref="numSelect">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>{' '}
<button onClick={this.increment}>+</button>{' '}
<button onClick={this.decrement}>-</button>{' '}
<button onClick={this.incrementIfOdd}>increment if odd</button>{' '}
<button onClick={this.incrementAsync}>increment async</button>
</div>
)
}
}