redux
- 数据管理模型,跟React没有关系
- 三大原则
- 单一数据源(所有的数据在一个对象里面)
- state是只读的
- 使用纯函数执行和修改
最基本的redux用法
// => store/index.js
import { createStore } from 'redux'
function reducer(state, action) {
// state就是数据源,action是一个带type属性的普通对象
state = state || {
name: '沫沫',
age: 18
}
switch(action.type) {
case 'changeName':
state.name = action.nnn
break;
case 'changeAge':
state.age = action.aaa
break;
}
return {
...state
}
}
let store = createStore(reducer)
export default store
- 使用
import React, { Component } from 'react'
import store from './index'
console.log(store)
export default class App extends Component {
componentDidMount() {
// 监听state的更新,添加一个回调函数
store.subscribe(() => {
console.log('数据更新了')
// 调用视图更新,可能会出现state更新了视图没有更新的情况
this.setState({})
})
}
render() {
// getState是获取state数据源的
let state = store.getState()
console.log(state)
return (
<div>
<h1>{state.name} --- { state.age }</h1>
<button onClick={() => {
store.dispatch({
type: 'changeName',
nnn: '瑞瑞'
})
}}>changeName</button>
<button onClick={() => {
store.dispatch({
type: 'changeAge',
aaa: 19
})
}}>changeAge</button>
</div>
)
}
}
store的项目处理
实际开发会根据不同的功能用不同的reducer
- 多个reducer的情况我们需要合并reducer
import { createStore, combineReducers } from 'redux'
import {
CHANGE_NAME,
CHANGE_AGE,
CHANGE_COLOR
} from './actionTypes'
function reducer(state, action) {
// state就是数据源,action是一个带type属性的普通对象
state = state || {
name: '沫沫',
age: 18
}
switch(action.type) {
case CHANGE_NAME:
state.name = action.nnn
break;
case CHANGE_AGE:
state.age = action.aaa
break;
}
return {
...state
}
}
function ColorReducer(state, action) {
state = {
color: 'red'
}
if(action.type === CHANGE_COLOR) {
state.color = action.color
}
return {
...state
}
}
// 合并reducer
let rootReducer = combineReducers({
userInfo: reducer,
colorInfo: ColorReducer
})
let store = createStore(rootReducer)
export default store
- action的type在实际工作中是会用常量来指定的
// => actionTypes.js
export const CHANGE_NAME = 'CHANGE_NAME'
export const CHANGE_AGE = 'CHANGE_AGE'
export const CHANGE_COLOR = 'CHANGE_COLOR'
- actions.js保存我们所需要的action的对象
- acttion必须是返回type属性的对象,默认情况是不能在这里调用请求的
- 这里如果像调用请求,需要一个中间件redux-thunk
- npm i redux-thunk
import {
CHANGE_NAME,
CHANGE_COLOR,
CHANGE_AGE
} from "./actionTypes";
export function changeName(name) {
return function (dispatch, getState) {
console.log(arguments)//=> dispatch, getState
// thunk中间件 可以让dispatch 接收一个函数作为 action
// 这个函数 会接收到对应 dispatch
// 其实 thunk 是让dispatch 执行的是把自身触发的reducer的功能转接给了对应的函数
// 说白了派发在这里执行了
// fetch('/ccc').then(data => {
// dispatch({
// type: CHANGE_NAME,
// nnn: name
// })
// })
new Promise((resolve, reject) => {
resolve(1)
}).then(res => {
dispatch({
type: CHANGE_NAME,
nnn: name
})
})
}
}
export function changeAge(age) {
return {
type: CHANGE_AGE,
aaa: age
}
}
export function changeColor(color) {
return {
type: CHANGE_COLOR,
color
}
}
- 使用
- 因为合并了reducer
- 在派发的时候也需要指定是哪个reducer执行,所有的reducer都会执行
import React, { Component } from 'react'
import store from './index'
import {
changeAge,
changeName,
changeColor
} from './actions'
export default class App extends Component {
componentDidMount() {
// 监听state的更新,添加一个回调函数
store.subscribe(() => {
console.log('数据更新了')
// 调用视图更新
this.setState({})
})
}
render() {
// getState是获取state数据源的
let state = store.getState()
console.log(state)
return (
<div style={{color: state.colorInfo.color}}>
<h1>{state.userInfo.name} --- { state.userInfo.age }</h1>
<button onClick={() => {
store.dispatch(changeName('瑞瑞'))
}}>changeName</button>
<button onClick={() => {
store.dispatch(changeAge(19))
}}>changeAge</button>
<button onClick={() => {
store.dispatch(changeColor('yellow'))
}}>改颜色</button>
</div>
)
}
}