安装redux devtools工具
打开
到chrome网上应用商店,搜索
点击 添加到Chrome
点击the instructions将下图代码添加到store的index.js文件
const store = createStore(
reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
操作完成 Redux下如图:
介绍redux使用流程
1.安装:yarn add redux
2.在src文件夹下创建store文件夹,并在store文件夹下创建index.js文件,在store目录下再创建ruducer.js
store文件夹中index.js
import { createStore } from 'redux';
import reducer from './reducer'
const store = createStore(reducer);
export default store;
reducer.js
const defaultState = {
inputValue:'123',
list: [1,2]
}
//state指的是整个store里的数据
export default (state = defaultState, action) => {
return state;
}
例1
在input中添加onChange方法使输入框输入文字改变,实现Input框的功能
handleInputChange(e){
const action = {
type: 'change_input_value',
value: e.target.value //现在的值
}
store.dispatch(action); //调用store.dispatch方法将action传给store,store会自动的把之前的数据和action转发给reducer.
console.log(e.target.value);
}
打开reducer,reducer可以接受传过来的state和action了
state指的是store里面上一次存储的数据,action指的是用户传过来的那句话。reducer对之前的数据进行处理返回一个新的数据给store:
//state指的是整个store里的数据
export default (state = defaultState, action) => {
if (action.type === 'change_input_value'){
//reducer可以接收state但绝对不可以修改state
//对之前的state进行深拷贝
const newState = JSON.parse(JSON.stringify(state));
//让newState的inputValue等于新的传过来的新的value值
newState.inputValue = action.value;
return newState;//return出来的数据实际上返回给了store,store用新数据替换旧数据
}
// console.log(state, action);
return state;
}
reducer处理完数据并store更新完数据之后,在组件中做如下处理使组件更新:
在组件中,例如Todolist.js组件中的constructor中添加store.subscribe();
去订阅store,只要store改变store.subscribe()里的函数就会被执行。
constructor(props) {
super(props);
this.state = store.getState();
this.handleStoreChange = this.handleStoreChange.bind(this);
store.subscribe(this.handleStoreChange);
}
handleStoreChange(){
// console.log('store changed');
//当我感知到store的数据发生变化的时候,就调用store.getState()方法从store里面重新取一次数据,然后调用setState替换掉当前组件里的数据。
this.setState(store.getState());
}
例2
做Todolist列表功能,当点击提交按钮时,把输入的数据存到
const defaultState = { inputValue:'123', list: [1,2] }
的list数组中:
在组件中给提交按钮绑定事件:
<Button type="primary" onClick={this.handleBtnClick}>提交</Button>
1.创建action,并发给store,store将之前数据以及action转发给reducer
handleBtnClick(){
const action = {
type: 'add_todo_item'
};
store.dispatch(action);
}
2.reducer对之前的数据进行处理返回一个新的数据给store
if (action.type === 'add_todo_item') {
const newState = JSON.parse(JSON.stringify(state));
//把之前的输入的inputValue放到newState的列表当中
newState.list.push(newState.inputValue);
//同时清空输入框
newState.inputValue = '';
console.log(newState);
return newState;
}
3.之前已经订阅了store,只要store改变store.subscribe()里的函数就会被执行
constructor(props) {
super(props);
this.state = store.getState();
this.handleStoreChange = this.handleStoreChange.bind(this);
store.subscribe(this.handleStoreChange);
}
handleStoreChange(){
// console.log('store changed');
//当我感知到store的数据发生变化的时候,就调用store.getState()方法从store里面重新取一次数据,然后调用setState替换掉当前组件里的数据。
this.setState(store.getState());
}
例3
1.删除功能,在Todolist.js中list组件中添加删除方法
<List
style={{marginTop: '10px', width: '300px'}}
bordered
dataSource={this.state.list}
renderItem={(item, index) => <List.Item onClick={this.bandleItemDelete.bind(this, index)}>{item}</List.Item>}
/>
bandleItemDelete(index){
const action = {
type:'delete_todo_item',
index
}
store.dispatch(action);
}
2.reducer中
if (action.type === 'delete_todo_item'){
const newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.index, 1)//第一个参数值得是第几个,第二个参数指删除的数量
return newState;
}
3.之前已经订阅了store,只要store改变store.subscribe()里的函数就会被执行
constructor(props) {
super(props);
this.state = store.getState();
this.handleStoreChange = this.handleStoreChange.bind(this);
store.subscribe(this.handleStoreChange);
}
handleStoreChange(){
// console.log('store changed');
//当我感知到store的数据发生变化的时候,就调用store.getState()方法从store里面重新取一次数据,然后调用setState替换掉当前组件里的数据。
this.setState(store.getState());
}
到这里就结束了。
下面是页面完整代码:
store文件夹下index.js代码
import { createStore } from 'redux';
import reducer from './reducer'
const store = createStore(
reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
export default store;
store文件夹下reducer.js代码:
const defaultState = {
inputValue:'123',
list: [1,2]
}
//state指的是整个store里的数据
export default (state = defaultState, action) => {
if (action.type === 'change_input_value'){
//对之前的state进行深拷贝
const newState = JSON.parse(JSON.stringify(state));
//让newState的inputValue等于新的传过来的新的value值
newState.inputValue = action.value;
return newState;
}
if (action.type === 'add_todo_item') {
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue = '';
console.log(newState);
return newState;
}
if (action.type === 'delete_todo_item'){
const newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.index, 1)
return newState;
}
return state;
}
Todolist组件的代码:
import React, {Component} from 'react';
import 'antd/dist/antd.css';
import { Button,List,Input } from 'antd';
import store from './store/index';
class TodoList extends Component{
constructor(props) {
super(props);
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
store.subscribe(this.handleStoreChange);
}
render() {
return (
<div style={{margin:'10px'}}>
<div>
<Input
value={this.state.inputValue}
placeholder='todo info'
style={{width:'300px', marginRight:'10px'}}
onChange={this.handleInputChange}
/>
<Button type="primary" onClick={this.handleBtnClick}>提交</Button>
</div>
<List
style={{marginTop:'10px',width:'300px'}}
bordered
dataSource={this.state.list}
renderItem={(item, index) => <List.Item onClick={this.bandleItemDelete.bind(this, index)}>{item}</List.Item>}
/>
</div>
)
}
handleInputChange(e){
const action = {
type: 'change_input_value',
value: e.target.value
}
store.dispatch(action);
console.log(e.target.value);
}
handleStoreChange(){
// console.log('store changed');
this.setState(store.getState());
}
handleBtnClick(){
const action = {
type: 'add_todo_item'
};
store.dispatch(action);
}
bandleItemDelete(index){
const action = {
type:'delete_todo_item',
index
}
store.dispatch(action);
}
}
export default TodoList;
ActionTypes的拆分
创建actionTypes.js ,
export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DELETE_TODO_ITEM = 'delete_todo_item';
到todolist和reducer中引入常量
import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM} from './store/actionTypes'
import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM} from './actionTypes'
将所有所有type换成定义的 例如:
handleInputChange(e){
const action = {
type:CHANGE_INPUT_VALUE,
value:e.target.value
}
store.dispatch(action);
}
if (action.type === CHANGE_INPUT_VALUE){
const newState = JSON.parse(JSON.stringify(state));
newState.inputValue = action.value;
return newState;
}
使用actionCreater统一创建action
提高代码的可读性,方便自动化测试 。
创建actionCreators.js
import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM} from './actionTypes'
export const getInputChangeAction = (value)=>({
type: CHANGE_INPUT_VALUE,
value
});
export const getAddItemAction = () => ({
type: ADD_TODO_ITEM,
});
export const getDeleteItemAction = (index)=>({
type:DELETE_TODO_ITEM,
index
})
Todolist.js中引入
import {getInputChangeAction,getAddItemAction,getDeleteItemAction} from './store/actionCreators'
handleInputChange(e){
const action = getInputChangeAction(e.target.value);
store.dispatch(action);
}
handleBtnChange(){
const action = getAddItemAction();
store.dispatch(action);
}
bandleItemDelete(index){
const action = getDeleteItemAction(index);
store.dispatch(action);
}