由浅及深,学习 react!
redux :是一个应用数据流框架,主要是解决了组件间状态共享的问题,原理是集中式管理。
React-redux:是为方便react使用,在redux上封装的库。在实际的项目中我们可以使用redux也可以直接使用react-redux
概念:
- 管理数据源
- action :是一个对象,根据type用来描述state发生了怎么样的变化 ,
- action:redux将每一个修改state的动作定义为一个action,需要更改state,则需要发送一个action
- reducer:就是根据 action来操作 state
- store: 就是保存整个数据的地方,只能有一个store
- dispatch :store.dispatch()是组件发出action的唯一方式
实现:
安装:
npm install redux
以下以一个完整的todoList的案例介绍
创建store目录(在src目录下) 如下
| |-- store //状态管理目录
| | |-- actionCreators.js
| | |-- actionTypes.js
| | |-- index.js
| | |-- reducer.js
index.js
import { createStore } from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
export default store ;//将store注入到根组件 index.js
actionTypes.js
分类管理,思路清晰
export const CHANGE_INPUT_VALUE = 'change_input_value'
export const ADD_ITEM = 'add_item'
export const DELETE_ITEM = 'delete_item'
export const START_GETLIST = 'start_getlist'
export const SUCCESS_GETLIST = 'success_getlist'
export const GET_DATA_SUCCESS = 'get_data_success'
actionCreactors.js
定义action及type ,告诉reducer如何处理action
import {
CHANGE_INPUT_VALUE,
ADD_ITEM,
DELETE_ITE,
} from './actionTypes'
// 抛出方法到具体组件中去
export const changeInputValueAction = (value) => ({
type:CHANGE_INPUT_VALUE,
value:value
})
export const submitInputValueAction = () => ({
type:ADD_ITEM
})
export const deleteItemAction = (index) => ({
type:DELETE_ITEM,
index
})
reducer.js
更新state
const defaultState = {
inputValue:'',
todoList:[],
}
export default (state = defaultState,action) => {
console.log(action.type)
if( action.type === 'change_input_value' ){
const newState = JSON.parse(JSON.stringify(state))
newState.inputValue = action.value
return newState
}
if( action.type === 'add_item' ){
const newState = JSON.parse(JSON.stringify(state))
if(newState.inputValue != ''){
newState.todoList.push(newState.inputValue)
newState.inputValue = ''
return newState
}
}
if( action.type === 'delete_item' ){
const newState = JSON.parse(JSON.stringify(state))
newState.todoList.splice(action.index,1)
return newState
}
return state
}
项目入口js文件 index.js
注入react-redux,借用Provider将store注入到全局
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store/index';// 引入store
import { hot } from 'react-hot-loader/root';//修改热更新
import Routes from '@router/router';
import 'antd/dist/antd.css';
const HotRoutes = hot(Routes)
const AppView = (
<Provider store={store}>
<HotRoutes />
</Provider>
)
ReactDOM.render(AppView, document.getElementById("root"))
组件中使用
TodoList.js
import React , { Component } from 'react'
import { connect } from 'react-redux'
import {changeInputValueAction, submitInputValueAction, deleteItemAction} from '../store/actionCreators'
import {Form, Input, Button, Checkbox, List, Typography, Divider } from 'antd';
const TodoList = (props) => {
console.log('Todolist',props);
const { inputValue,list, changeInputValue,submitInputValue,deleteItem} = props
const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 8 },
};
const tailLayout = {
wrapperCol: { offset: 8, span: 16 },
};
const formRef = React.createRef();
const onFinish = (e) => {
formRef.current.setFieldsValue({
"inputValue": "",
})
}
const onFinishFailed = () => {
}
return (
<div >
<div className="form-wrap">
<Form
className='form-todolist'
{...layout}
name="basic"
initialValues={{ remember: true }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
ref={formRef}
>
<Form.Item
label="Username"
name="inputValue"
rules={[{ required: true, message: 'Please input your username!' }]}
>
<Input onChange={changeInputValue}/>
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit" onClick={submitInputValue}>
Submit
</Button>
</Form.Item>
</Form>
</div>
<List
header={''}
footer={''}
bordered
dataSource={list}
renderItem={(item,index) => (
<List.Item onClick={ () => {deleteItem(index)}}>
<Typography.Text mark>[ITEM]</Typography.Text> {item}
</List.Item>
)}
/>
</div>
)
}
// store中的数据与组件的数据做映射
const mapStateToProps = (state) => {
return {
inputValue:state.inputValue,
list:state.todoList
}
}
// store.dispatch , props 派发
const mapDispatchToProps = (dispatch) => {
return {
changeInputValue(e) {
const action = changeInputValueAction(e.target.value)
console.log(action)
dispatch(action)
},
submitInputValue(){
const action = submitInputValueAction()
dispatch(action)
},
deleteItem(index){
const action = deleteItemAction(index)
dispatch(action)
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(TodoList)
关键代码:mapStateToProps 与 mapDispatchToProps
属性和方法使用方式:this.props.XXX 或者 在 const { XXX, XXX } = props
举例 changeInputValue方法为组件内定义的方法,调用action中的方法 changeInputValueAction,通过mapDispatchToProps 下的 dispatch 触发一个action,
reducer根据type类型处理相应的逻辑,更新state,组件内通过 mapStateToProps获取新的映射,在组件内通过 this.props.更新新的属性