1、Redux 入门
1-1、概念
1-2、Redux 的工作流程
简单理解
流程理解:图书馆
react components :借书的人
action Creatos: 你说的 借什么书 这句话
store: 图书馆管理员
Reducers: 记录本
借书人(react components)说,我要借一本名为围城的书(action creators),给图书馆管理员说(store),图书馆管理员(store)去记录本(reducers)中查找这本书,给借书人(react components);
工作流程详解
1、react 首先去改变store中数据,先要派发一个action,action会通过dispatch方法传递给store;
2、store会把之前的数据和action转发给reducer;
3、reducer是一个函数,接收到action和state之后,会做一些处理之后返回一个新的state给store;
4、store再用新的state替换掉之前的数据;
5、store中的数据发生改变后,react会感知到store中数据改变,然后从store中重新去取数据,更新组件的内容,页面就跟着发生变化;
1-3、Redux 的使用
index.js
import React from 'react';
import store from './store'
import TodoListUI from './TodoListUI'
import {handleInputChange, handleListValue, handleDeleteItem} from './store/actionCreator'
class TodoList2 extends React.Component {
constructor(props) {
super(props);
this.state = store.getState()
// 订阅store
store.subscribe(this.handleStoreChange)
}
// store中state发生改变
handleStoreChange = () => {
this.setState(store.getState())
console.log('store change')
}
handleInputChange = (e) => {
const action = handleInputChange(e.target.value)
store.dispatch(action)
}
handleClick = () => {
const action = handleListValue()
store.dispatch(action)
}
iconClick = (index) => {
const action = handleDeleteItem(index)
store.dispatch(action)
}
componentDidMount() {
// axios.get('/list.json').then(res => {
// console.log(res)
// const data = res.data
// store.dispatch(data)
// })
}
render() {
return <TodoListUI
handleInputChange={this.handleInputChange}
inputValue={this.state.inputValue}
handleClick={this.handleClick}
list={this.state.list}
iconClick={this.iconClick}
/>
}
}
export default TodoList2
TodoListUI.js
import React from 'react';
import {Input, List, Button} from "antd";
const TodoListUI = (props) => {
return (
<div>
<Input
value={props.inputValue}
onChange={props.handleInputChange}
style={{marginBottom: '10px', width: '210px', marginRight: '10px'}}/>
<Button type="primary" onClick={props.handleClick}>submit</Button>
<List
style={{width: '300px'}}
size="large"
header={<div>Header</div>}
footer={<div>Footer</div>}
bordered
dataSource={props.list}
renderItem={(item, index) => <List.Item onClick={(index) => props.iconClick(index)}>
{item}
</List.Item>}
></List>
</div>
)
}
export default TodoListUI
index.js
import {createStore, applyMiddleware} from "redux";
import reducer from './reducer'
import thunk from 'redux-thunk'
const store = createStore(
reducer,
applyMiddleware(thunk)
)
export default store
actionType.js拆分
export const DELETE_LIST_ITEM = 'delete_list_item'
export const CHANGE_INPUT_VALUE = 'change_input_value'
export const CHANGE_LIST_VALUE = 'change_list_value'
actionCreator 统一创建 action
import {DELETE_LIST_ITEM, CHANGE_LIST_VALUE, CHANGE_INPUT_VALUE} from './actionTypes'
export const handleInputChange = (value) => ({
type: CHANGE_INPUT_VALUE,
value
})
export const handleListValue = () => ({
type: CHANGE_LIST_VALUE,
})
export const handleDeleteItem = (index) => ({
type: DELETE_LIST_ITEM,
index
})
reducer.js
import {DELETE_LIST_ITEM, CHANGE_LIST_VALUE, CHANGE_INPUT_VALUE} from './actionTypes'
const defaultStore = {
inputValue: '',
list: []
}
export default function reducer(state = defaultStore, action) {
if (action.type === CHANGE_INPUT_VALUE) {
const newValue = JSON.parse(JSON.stringify(state))
newValue.inputValue = action.value
return newValue
} else if (action.type === CHANGE_LIST_VALUE) {
const newValue = JSON.parse(JSON.stringify(state))
newValue.list.push(newValue.inputValue)
newValue.inputValue = ''
return newValue
} else if (action.type === DELETE_LIST_ITEM) {
const newValue = JSON.parse(JSON.stringify(state))
newValue.list.splice(action.index, 1)
return newValue
}
return state
}
1-4、Redux 设计和使用的三大原则
1-5、Redux 中核心API
createStore: 创建store
store.dispatch: 派发action,action会传递给store
store.getState: 可以获取store里面所有的数据内容
store.subscribe: 订阅store的改变,只要store发生改变,store.subscribe接收的回调函数就会被执行
2、Redux 进阶
2-1、Redux-thunk 中间件可以在action中进行ajax异步请求
redux-thunk链接
接口请求写在 componentDidMount()中,代码多的话,显得冗余:
使用redux-thunk统一管理:通过redux 创建store的时候,可以使用中间件,这个中间件是redux的中间件
然后就可以在action中进行异步请求:
2-2、什么是 redux 中间件 ?
中间件指的是:action 和store的中间,所以指的是redux的中间件。
2-3、 redux-saga 中间件的使用
redux-saga使用链接
没有中间件的时候,ajax异步请求写在生命周期中:
使用 redux-saga
在 redux-saga中进行异步请求
2-4、react-redux 的使用
1、 安装: npm install react-redux
2、在main.js 中引入 react-redux,provider的意思: provider里面的所有组件都可以获取store的内容.
3、 在组件中使用 connect 方法,让当前组件和store进行连接。
mapStateToProps: 把store中的数据(state)映射给组件,变成组件的props,在组件中用{this.props.inputValue}的方式使用;
mapDispatchToProps:Diapatch => store.dispatch, Props => props
import React, { PureComponent } from 'react';
import { Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import { LoginWrapper, LoginBox, Input, Button } from './style';
import { actionCreators } from './store';
class Login extends PureComponent {
render() {
const { loginStatus } = this.props;
if (!loginStatus) {
return (
<LoginWrapper>
<LoginBox>
<Input placeholder='账号' innerRef={(input) => {this.account = input}}/>
<Input placeholder='密码' type='password' innerRef={(input) => {this.password = input}}/>
<Button onClick={() => this.props.login(this.account, this.password)}>登陆</Button>
</LoginBox>
</LoginWrapper>
)
}else {
return <Redirect to='/'/>
}
}
}
const mapState = (state) => ({
loginStatus: state.getIn(['login', 'login'])
})
const mapDispatch = (dispatch) => ({
login(accountElem, passwordElem){
dispatch(actionCreators.login(accountElem.value, passwordElem.value))
}
})
export default connect(mapState, mapDispatch)(Login);