1.redux是什么?
新名词:reducer、store、dispatch、middleware state
1.)redux是一个独立专门用于做状态管理的js库(不是react插件库)
2.)它可以在react,angular,vue等项目中,但基本与react配合使用
3.)作用:集中式管理react应用中多个组件共享的状态
4.)开发:与react-redux,redux-thunk等插件配合使用
开始前,你必须知道一些事情:
redux 和 react 没有关系,redux 可以用在任何框架中,忘掉 react。
connect 不属于 redux,它其实属于 react-redux,请先忘掉它
请一定先忘记 reducer、store、dispatch、middleware 等等这些名词。
redux 是一个状态管理器。
2.什么时候用redux
1.某个组的状态需要共享
2.某个状态需要在任何地方都可以拿到
3.一个组件需要改变全局状态
4.一个组件需要改变另一个组件的状态
3.redux相关API
redux中包含:createStore(),applyMiddleware(),combineReducers()
store对象:getStore(),dispatch(),subscribe()
react-redux:
<Provider store={store}>:向所有的容器组件提供store
connect(
mapStateToProps,
mapDispatchToProps
)(UI组件)
4.redux核心概念(3个)
action:
默认是对象(同步action),{type:‘xxx’,data:value},需要通过对应的actionCreator产生
它的默认是也可以是函数(异步action),需要引入redux-thunk才可以
reducer:
根据老的state和指定的action,返回一个新的state,不能修改老的state
store:
redux最核心的管理对象,
内部管理者:state和reducer
提供方法:getState(),dispatch(action),subscribe(listener)
react-redux
1.理解:
是一个react插件库
专门用来简化react应用中使用redux
2.UI组件
只负责UI的呈现,不带有任何业务逻辑
通过props接收数据(一般数据和函数)
不使用任何redux的API
一般保存在components的文件下
3.容器组件
容器组件:通过connect包装UI组件产生组件
connect():高阶函数
connect()返回的函数是一个高阶组件:接收一个UI组件,生成一个容器组件
容器组件的责任:想UI组件传入特定属性
redux-thunk
redux 默认是不能进行异步处理的
应用中又需要在redux中执行异步任务(ajax 定时器)
thunk(异步中间件)异步增加的异步 action
export const incrementAsync = function (number) {
// 返回一个带 dispatch 参数的函数
return dispatch => {
// 执行异步操作
setTimeout(() => {
// 有了结果后 , 分发同步 action
dispatch(increment(number))
}, 1000)
}
}
第一个文件store.js
import {createStore} from "redux";
import reducer from "./reducer";
// 这里的window.后面的一大堆是用于Chrome的redux devtools插件使用的
const store = createStore(reducer, window .__REDUX_DEVTOOLS_EXTENSION__ && window .__REDUX_DEVTOOLS_EXTENSION__());
export default store;
第二个文件reducer.js
import {CHANGE_INPUT_VALUE,ADD_TO_ITEM,DELETE_TO_ITEM} from'./actiontypes'
const defaultState = {
inputValue: '123',
list: [1, 2, 3]
};
// 初始化状态--传入一个初始的state对象
// 暴露出去的是一个纯函数(有固定的输入就有固定的输出)没有副作用
export default (state = defaultState, action) => {
if (action.type===CHANGE_INPUT_VALUE){
// 深拷贝传入的state
// redux不能直接修改state,只能复制成一个新的newstate,
// 修改newstate,
// 最后返回newstate
const newState=JSON.parse(JSON.stringify(state));
newState.inputValue=action.value;
return newState;
}
if (action.type===ADD_TO_ITEM){
const newState=JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue='';
return newState;
}
if (action.type===DELETE_TO_ITEM){
const newState=JSON.parse(JSON.stringify(state));
newState.list.splice(action.index,1);
return newState;
}
return state;
}
第三个文件actionCreaters.js
import {CHANGE_INPUT_VALUE, ADD_TO_ITEM, DELETE_TO_ITEM} from './actiontypes'
// 构建action的函数
export const changeInputValue = (value) => (
{
type: CHANGE_INPUT_VALUE,
value
}
);
export const addToItem = () => (
{type: ADD_TO_ITEM}
);
export const deleteToItem = (index) => (
{
type: DELETE_TO_ITEM,
index
}
);
第四个文件actiontypes.js
定义的action的type的值
export const CHANGE_INPUT_VALUE='change_input_value';
export const ADD_TO_ITEM='add_to_item';
export const DELETE_TO_ITEM='delete_to_item';
第五个文件最主要的组件部分todolist.js
import React, {Component} from "react";
import {Input, Button} from 'antd';
import {List, Typography, Divider} from 'antd';
import store from "./store/store";
import 'antd/dist/antd.css';
import {changeInputValue,addToItem,deleteToItem} from './store/actionCreaters'
export default class TodoList extends Component {
constructor(props) {
super(props);
// 从store得到初始的状态
this.state = store.getState();
// store的状态改变调用handleStoreChange函数
store.subscribe(this.handleStoreChange)
}
handleStoreChange = () => {
// 更新设置组件的状态
this.setState(store.getState());
};
handleChange = (e) => {
// input的value值变化,通过action传给store
const action = changeInputValue(e.target.value);
store.dispatch(action)
};
handleChick=()=>{
// 点击按钮实现添加功能,通过action传给store
const action=addToItem();
store.dispatch(action)
};
handleDelete=()=>{
// 点击list的列表实现删除功能,通过action传给store
const action=deleteToItem(this.props.key);
store.dispatch(action);
};
// 下面是组件的定义
render() {
return (
<div style={{margin: '10px'}}>
<Input placeholder="Basic usage" style={{width: '300px', margin: '10px'}}
value={this.state.inputValue} onChange={this.handleChange}/>
<Button type="primary" onClick={this.handleChick}>提交</Button>
<List
style={{width: '300px', marginLeft: '10px'}}
size="small"
bordered
dataSource={this.state.list}
renderItem={(item,index) => <List.Item key={index} onClick={this.handleDelete}>{item}</List.Item>}
/>
</div>
)
}
}