14.redux代码中使用19-05-15

安装redux devtools工具

打开

屏幕快照 2019-05-15 16.40.50.png

到chrome网上应用商店,搜索
屏幕快照 2019-05-15 16.46.49.png

点击 添加到Chrome
屏幕快照 2019-05-15 16.49.54.png

点击the instructions将下图代码添加到store的index.js文件
Snip20190515_1.png

const store = createStore(
  reducer,
   window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

操作完成 Redux下如图:


屏幕快照 2019-05-15 16.56.45.png

介绍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);
  }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容