知识点
action
官方的解释是action是把数据从应用传到 store 的有效载荷,它是 store 数据的唯一来源;要通过本地或远程组件更改状态,需要分发一个action
action type
action的type
reducer
action发出了做某件事的请求,只是描述了要做某件事,并没有去改变state来更新界面,reducer就是根据action的type来处理不同的事件
store
store就是把action和reducer联系到一起的对象,store本质上是一个状态树,保存了所有对象的状态。任何UI组件都可以直接从store访问特定对象的状态
开启redux工具
redux如果要使用google浏览器的redux工具调试,需要在createStore中加入
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
案例
创建Redux的仓库store和reducer并使用
默认已经使用 create-react-app 初始化好项目并且已经安装 redux 了
- 1、在src目录创建store文件夹并在文件夹中创建一个index.js文件
import { createStore } from 'redux' // 引入createStore
const store = createStore() // 创建数据存储仓库
export default store // 暴露出去
- 2、在store文件夹再创建reducer.js文件
const defaultState = { // 默认数据
inputValue: 'Write Something',
list: [
'早上6点起床,锻炼身体',
'晚上跑步一小时'
]
}
export default (state = defaultState, action) => { // 就是一个方法函数
return state
}
- 3、在store文件夹的index.js文件中引入reducer.js文件
index.js变成这样了
import { createStore } from 'redux' // 引入createStore
// ------------- 重点 ---------------
import reducer from './reducer' // 引入reducer
const store = createStore(reducer) // 创建数据存储仓库
export default store // 暴露出去
- 4、使用
在使用的文件中引入store,并在构造函数constructor中获取state
import store from './store'
constructor(props) {
super(props)
this.state = store.getState()
}
这样 redux 中的数据就和使用的地方产生关联了
加入Redux DevTools插件
在 reducer.js 中加入 window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
import { createStore } from 'redux' // 引入createStore
import reducer from './reducer' // 引入reducer
// ----------------- 重点 ----------------
const store = createStore(reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()) // 创建数据存储仓库
export default store // 暴露出去
加入这段代码后,就可以使用 redux 调试工具调试数据了
让redux工作起来
redux是管理数据的仓库,现在让他起作用吧!
- 1、给Input增加onChange事件
<Input
onChange={this.changeInputValue}
placeholder={this.state.inputValue}
style={{ width: '250px', marginRight: '10px' }} />
changeInputValue = (e) => {
const action = {
type: 'changeInputValue',
value: e.target.value
}
store.dispatch(action)
}
- 2、订阅reudx状态
constructor(props) {
super(props)
this.state = store.getState()
// 订阅redux状态
store.subscribe(this.storeChange)
}
storeChange = () => {
this.setState(store.getState())
}
- 3、在reducer.js中接收传过来的数据
export default (state = defaultState, action) => { // 就是一个方法函数
if(action.type === 'changeInputValue') {
let newState = JSON.parse(JSON.stringify(state)) // 深度拷贝state
newState.inputValue = action.value
return newState
}
return state
}
- 4、把两个文件的代码全都贴出来
// TodoList.js
import React, { Component } from 'react'
import 'antd/dist/antd.css'
import { Input, Button, List } from 'antd'
import store from './store'
export default class TodoList extends Component {
constructor(props) {
super(props)
this.state = store.getState()
// 订阅redux状态
store.subscribe(this.storeChange)
}
storeChange = () => {
this.setState(store.getState())
}
render() {
return (
<div style={{ margin: '10px' }}>
<div>
<Input
onChange={this.changeInputValue}
placeholder={this.state.inputValue}
style={{ width: '250px', marginRight: '10px' }} />
<Button type="primary">增加</Button>
</div>
<div style={{ margin: '10px', width: '300px' }}>
<List
bordered
dataSource={this.state.list}
renderItem={item => (
<List.Item>{item}</List.Item>
)}
>
</List>
</div>
</div>
)
}
// input输入
changeInputValue = (e) => {
const action = {
type: 'changeInputValue',
value: e.target.value
}
store.dispatch(action)
}
}
// reducer.js
const defaultState = { // 默认数据
inputValue: 'Write Something',
list: [
'早上6点起床,锻炼身体',
'晚上跑步一小时'
]
}
export default (state = defaultState, action) => { // 就是一个方法函数
if(action.type === 'changeInputValue') {
let newState = JSON.parse(JSON.stringify(state)) // 深度拷贝state
newState.inputValue = action.value
return newState
}
return state
}
把 Action Types 抽出来,单独写一个文件
- 1、在store中新建一个actionTypes.js文件
export const CHANGE_INPUT_VALUE = 'changeInputValue'
export const ADD_ITEM = 'addItem'
export const DELETE_ITEM = 'deleteItem'
- 2、在TodoList.js中引入并使用
import { CHANGE_INPUT_VALUE, ADD_ITEM, DELETE_ITEM } from './store/actionTypes'
// input输入
changeInputValue = (e) => {
const action = {
type: CHANGE_INPUT_VALUE,
value: e.target.value
}
store.dispatch(action)
}
// 点击按钮
clickBtn = () => {
const action = {
type: ADD_ITEM
}
store.dispatch(action)
}
// 删除todo
deleteItem = (index) => {
const action = {
type: DELETE_ITEM,
index
}
store.dispatch(action)
}
- 3、在reducer.js中引入并使用
import { CHANGE_INPUT_VALUE, ADD_ITEM, DELETE_ITEM } from './actionTypes'
import { Modal } from 'antd';
const defaultState = { // 默认数据
inputValue: '',
list: [
'早上6点起床,锻炼身体',
'晚上跑步一小时'
]
}
export default (state = defaultState, action) => { // 就是一个方法函数
// console.log(state ,action)
if (action.type === CHANGE_INPUT_VALUE) { // input输入
let newState = JSON.parse(JSON.stringify(state)) // 深度拷贝state
newState.inputValue = action.value
return newState
}
if (action.type === ADD_ITEM) { // 添加item
let newState = JSON.parse(JSON.stringify(state))
if (!newState.inputValue) {
Modal.error({
title: '提示信息',
content: '输入框不能为空!'
});
return
}
newState.list.push(newState.inputValue)
newState.inputValue = ''
return newState
}
if (action.type === DELETE_ITEM) { // 删除item
let newState = JSON.parse(JSON.stringify(state))
newState.list.splice(action.index, 1)
return newState
}
return state
}
把 Redux Action 抽出来
- 1、在store中新建actionCreators.js文件
import { CHANGE_INPUT_VALUE, ADD_ITEM, DELETE_ITEM } from './actionTypes'
export const changeInputAction = (value) => ({
type: CHANGE_INPUT_VALUE,
value
})
export const addItemAction = () => ({
type: ADD_ITEM
})
export const deleteItemAction = (index) => ({
type: DELETE_ITEM,
index
})
- 2、修改TodoList.js文件方法
import { changeInputAction, addItemAction, deleteItemAction } from './store/actionCreators'
// input输入
changeInputValue = (e) => {
// const action = {
// type: CHANGE_INPUT_VALUE,
// value: e.target.value
// }
const action = changeInputAction(e.target.value)
store.dispatch(action)
}
// 点击按钮
clickBtn = () => {
// const action = {
// type: ADD_ITEM
// }
const action = addItemAction()
store.dispatch(action)
}
// 删除todo
deleteItem = (index) => {
// const action = {
// type: DELETE_ITEM,
// index
// }
const action = deleteItemAction(index)
store.dispatch(action)
}
redux的三个注意要点
- 1、store必须是唯一的,不能有多个
- 2、只有store能改变自己的内容,Reducer不能改变
- 2、Reducer必须是纯函数
网友评论