1、redux使用
- 了解
redux
redux是一个独立专门用于做状态管理的js库(不是react的插件库)redux可以在react,angular, vue等项目中使用,但大多数情况下,都是配合react适用redux是集中管理应用中多个组件共享的状态
- redux工作流
- 首先,用户发出action;
- 然后store自动调用reducer,并且传入两个参数,当前State和收到的Action, Reducer会返回新的State;
- views会根据store数据的改变执行页面刷新渲染的操作。
- 什么情况下使用redux
- 某个组件的状态需要共享;
- 某个状态需要在任何地方都可以拿到;
- 一个组件需要改变全局状态;
- 一个组件需要改变另一个组件的状态;
- redux的api
- createStore()
作用:创建包含指定reducer的store对象
编码:
import {createStore} from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
- store对象
作用:redux库最核心的管理对象
它内部维护者: state,reducer
核心方法:getState()、dispatch(action)、subscribe(listener)
使用:
store.getState()
store.dispatch({type:'INCREMENT',number})
store.subscribe(render)
- applyMiddleware()
作用:基于redux 的中间件(插件库)
编码:
import {createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'. //redux异步中间件
const store = createStore(
conunter,
applyMiddleware(thunk) //应用上异步中间件
)
4.combineReducers()
作用:合并多个reducer函数
编码:
export default combineReducers({
user,
tagLister,
chat,
})
2、redux的和心概念
- action
1、标识要执行行为的对象
1、包含两个方面的属性
a. type: 标识属性,值为字符串,唯一,必要属性
b. 数据属性,值类型任意,可选属性
3、例子:
const action = {
type: 'ADD',
data: 2
}
4、action creater(创建Action的工厂函数)
const increment = (num) => ({type: 'ADD', data: num})
- reducer
1、根据老的state和action,产生新的state的纯函数
2、样例
export default function counter(state = 0, action) {
switch(action.type) {
case 'ADD':
return state + action.data;
default:
return state;
}
}
3、注意:
a、返回一个新的状态
b、不要修改原来的状态
- store
1、将state、action和reducer联系在一起的对象
2、如何得到此对象?
import {createStore} from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
3、此对象的功能
getState() 得到state
dispatch(action): 分发action,触发reducer调用,产生新的state
subscribe(listener): 注册监听,当产生了新的state时,自动调用
3、redux使用例子
1、新建文件夹:redux
2、新建redux/action-type.js
/* action对象的type常量名称模块 */
export const ADD = 'add'
export const REMOVE = 'remove'
3、新建redux/action.js
/* action creater 模块
包含n个action creator函数
*/
import {ADD, REMOVE} from './action-type.js'
imoirt const add = (num) => ({type: ADD, num})
import const remove = (num) => ({type: REMOVE, num})
4、新建redux/reducer.js
import {ADD, REMOVE} from './action-type.js'
export default function count(state = 0, action) {
switch (action.type) {
case ADD:
return state + action.num;
case REMOVE:
return state - action.num;
default:
state;
}
}
5、新建redux/store.js
/* redux最核心的管理对象store */
import {createStore} from 'redux';
import reducer from './reducer';
export default createStore(reducer);
6、APP.jsx
import React,{Component} from 'react';
import PropTypes from 'prop-types';
import {add, remove} from './redux/action.js';
// 应用组件
export default class App extends Component {
static propTypes = {
store: ProtoTypes.object.isRequired
}
constructor (props) {
super(props)
this.numRef = React.createRef()
}
add = () => {
const num = this.numRef.current.value*1
this.props.store.dispatch(add(num))
}
remove = () => {
const num = this.numRef.current.value * 1
this.props.store.dispatch(remove(num))
}
render() {
const count = this.props.store.getState()
return (
<div>
<p>当前值 {count}</p>
<input ref={this.numRef} value={count}/>
<button onClick={this.add}>+</button>
<button onClick={this.remove}>-</button>
</div>
)
}
}
7、index.js
/* 入口js. */
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import store from './redux/store'
/* 将store 传递给App组件。*/
ReactDOM.render(
<APP store={store} />,
document.getElementById('root')
)
/* 通过store订阅state改变的监听 =》 一旦store中的state改变了,立即调用回调函数。*/
store.subscribe(() => {
React.render(
<APP store={store} />,
document.getElementById('root')
)
})
4、react-redux
- react-redux将所有组件分为两类
- UI组件
a. 只负责UI的呈现,不带有任何业务逻辑
b. 通过props接收数据
c. 不使用任何redux的API
d. 一般保存在components文件夹下
- 容器组件
a. 负责管理数据和业务逻辑,不负责UI的呈现
b. 适用Redux的API
c. 一般保存在containers 文件夹下
- react-redux的api
Provider
/* 让所有组件都可以得到state数据 */
<Provider store={store}><App/></Provider>
connect
/* 用于包装UI组件生成容器组件 */
connect(
mapStateToprops,
mapDispatchToprops
)(Counter)
mapStateToprops
/* 函数:将state数据转换为UI组件的标签属性 */
function mapStateToProps(state){
return {
count: state
}
}
mapDispatchToprops
/* 将分发action的函数转换为UI组件的标签属性 */
function mapDispatchToProps(dispatch) {
return {
add: (num) => dispatch(add(num)),
remove: (num) => dispatch(remove(num)),
}
}
//对象: 简洁语法,可以直接指定包含多个action方法
const mapDispatchToProps = {
add,
remove,
}
-
react-redux的使用
1、下载以来包:
npm install --save react-redux2、redux/action-type.js. 不变
3、redux/action.js. 不变
4、redux/reducers.js. 不变
5、redux/ store.js. 不变
6、components/Counter.jsx
import React, {Component} from 'react'
import PropTypes from 'prop-types'
/* 应用组件 */
export default class Counter extends Component {
static propTypes = {
count: PropTypes.num.isRequired,
add: PropTypes.func.isRequired,
remove: PropTypes.func.isRequired,
}
constructor (props) {
super(props)
this.numRef = React.createRef()
}
add = () => {
const num = this.numRef.current.value * 1
this.props.add(num)
}
remove = () => {
const num = this.numRef.current.value * 1
this.props.remove(num)
}
render() {
const count = this.props.count
return (
<div>
<p>当前count{count}</p>
<input ref={this.numRef} value={count}/>
<button onClick={this.add}>+</button>
<button onClick={this.remove}>-</button>
</div>
)
}
}
7、containters/App.jsx
/* 包装UI组件的容器组件,通过connec()生成 */
import React from 'react'
import {connect} from 'react-redux'
import Counter from '../components/Counter'
import {add, remove} from '../redux/actions'
/* functionmapStateToProps(state) {
return {
count:state
}
}
functionmapDispatchToProps(dispatch) {
return {
add:(num) => dispatch(add(num)),
remove:(num) => dispatch(remove(num)),
}
}
const mapDispatchToProps = {add,remove}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Counter) */
export default connect(
state => (count: state}),
{add, remove}
)(Counter)
8、index.js
/* 入口js */
import React from 'react'
import ReactDOM from 'react-dom'
import {Provider} from 'react-redux'
import App from './containers/App'
import store from './redux/store' //引入store
//将store 传递给Provider组件
ReactDOM.render((
<Provider store={store}>
<App />
<Provider>
), document.getElementById('root'))
- redux异步编程
1、下载redux-thunk插件
npm install --save redux-thunk2、redux/store.js
/* redux最核心的管理对象store */
import {createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import reducer from './reducer'
export default createStore(reducer, applyMiddleware(thunk))
3、redux/action.js
/* 增加异步的action */
export const addAsync = function(num) {
// 返回一个带dispatch参数的函数
return dispatch => {
setTimeout(() => {
dispatch(add(num))
}, 1000)
}
}
4、redux/Counter.jsx
/* */
static propTypes = {
count: PropTypes.num.isRequired,
add: PropTypes.func.isRequired,
remove: PropTypes.func.isRequired,
addAsync: PropTypes.func.isRequired,
}
addAsync = () => {
const num = this.numRef.current.value * 1
this.props.addAsync(num)
}
5、containers/App.jsx
import {addAsync} from '../redux/actions'
/* 向外暴露连接App组件的包装组件 */
export default connect(
state => ({count: state}),
{addAsync}
)(Counter)