美文网首页
14.redux代码中使用19-05-15

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

作者: 你坤儿姐 | 来源:发表于2019-05-16 12:03 被阅读0次

安装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);
  }

相关文章

网友评论

      本文标题:14.redux代码中使用19-05-15

      本文链接:https://www.haomeiwen.com/subject/vliuaqtx.html