(23)Redux 入门——⑤ actionTypes 的拆分 | React 基础理论实操

转载请注明出处,未经同意,不可修改文章内容。

🔥🔥🔥"前端一万小时"两大明星专栏------"从零基础到轻松就业"、"前端面试刷题",已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。

javascript 复制代码
涉及面试题:
1. 在 React 中如何定义常量?
2. Redux 中常量的用途是什么?

编号:[react_23]

1 为什么要拆分 actionTypes

紧接上一篇代码(请自行打开编辑器查看代码),我们可以很明显地看到:

  • TodoList.js 文件中,需要不断地派发 action 。然后,每个 action 又有一个 type ,且对应一串"字符串";

  • reducer.js 文件中,reducer 接收 actiontype 时,其"字符串"必须和 TodoList.jstype 对应的字符串"一模一样"!

这会带来什么问题呢?

我们在写代码的时候,偶尔会犯一些"笔误"。比如,在 TodoList.js 文件中,我们把 handleInputChange 方法里 type 对应的"字符串" "change_input_value" ,写成了 "change_inpvt_value"

jsx 复制代码
import React, {Component} from "react";
import 'antd/dist/antd.css';

import { Input, Button, List } from 'antd';  

import store from "./store";

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.handleButtonClick = this.handleButtonClick.bind(this); 
    
    store.subscribe(this.handleStoreChange);  
    
  }
  
  render() {
    return (
      <div style={{marginTop: "10px", marginLeft: "10px"}}>
        <div>
          <Input 
            value={this.state.inputValue} 
            placeholder="todo info" 
            style={{width: "300px", marginRight: "10px"}} 
            
            onChange={this.handleInputChange}  
          /> 
          
          <Button type="primary" onClick={this.handleButtonClick}>提交</Button>  

          <List style={{marginTop: "10px", width: "300px"}} 

            bordered
            dataSource={this.state.list}
            renderItem={(item, index) => <List.Item onClick = {this.handleItemDelete.bind(this, index)}>{item}</List.Item>}
          /> 
          
        </div>
      </div>
    )
  }
  
  handleInputChange(e) { 
    const action = {
      type: "change_inpvt_value", // ❗️❗️❗️input 错写成 inpvt!
      
      value: e.target.value  
    }
    
    store.dispatch(action);  
  }

  handleStoreChange() { 
    
    this.setState(store.getState()); 
  }

  handleButtonClick() { 
    const action = {  
      type: "add_todo_item" 
    };
    
    store.dispatch(action); 
  }

  handleItemDelete(index) {  
    
    const action = {
      type: "delete_todo_item",  
      index 
    };
    
    store.dispatch(action);  
  } 

}

export default TodoList;

我们可能会想,既然单词拼错了,控制台肯定会报错吧。

返回页面查看(程序不运行,但控制台却没任何报错):

❗️这种"字符串"拼写的小错误,在没有"报错"的提示下,没准就会耗费你几个小时的时间找 bug。

2 拆分 actionTypes 的步骤

❓这种情况可以怎么解决呢?

答:

1️⃣在 store 目录下,新建一个 actionTypes.js 文件。

2️⃣在 actionTypes.js 文件里,将之前 actiontypes 属性对应的"字符串 "赋值给同名的"常量",并把这个"常量"导出。

javascript 复制代码
export const CHANGE_INPUT_VALUE = "change_input_value";
export const ADD_TODO_ITEM = "add_todo_item";
export const DELETE_TODO_ITEM = "delete_todo_item";

3️⃣接着,在 TodoList.jsreducer.js 文件中将上边定义的常量"引入",并用"常量"替换所有的"字符串"。

TodoList.js 文件:

javascript 复制代码
import React, {Component} from "react";
import 'antd/dist/antd.css';

import { Input, Button, List } from 'antd';  

import store from "./store";

// 3️⃣-①:引入"常量";
import {CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM} from "./store/actionTypes"; 

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.handleButtonClick = this.handleButtonClick.bind(this); 
    
    store.subscribe(this.handleStoreChange);  
    
  }
  
  render() {
    return (
      <div style={{marginTop: "10px", marginLeft: "10px"}}>
        <div>
          <Input 
            value={this.state.inputValue} 
            placeholder="todo info" 
            style={{width: "300px", marginRight: "10px"}} 
            
            onChange={this.handleInputChange}  
          /> 
          
          <Button type="primary" onClick={this.handleButtonClick}>提交</Button>  

          <List style={{marginTop: "10px", width: "300px"}} 

            bordered
            dataSource={this.state.list}
            renderItem={(item, index) => <List.Item onClick = {this.handleItemDelete.bind(this, index)}>{item}</List.Item>}
          />  
          
        </div>
      </div>
    )
  }
  
  // 3️⃣-②:用"常量"替换掉"字符串";
  handleInputChange(e) { 
    const action = {
      type: CHANGE_INPUT_VALUE, 
      
      value: e.target.value  
    }
    
    store.dispatch(action);  
  }

  handleStoreChange() { 
    
    this.setState(store.getState()); 
  }

  handleButtonClick() { 
    const action = {  
      type: ADD_TODO_ITEM 
    };
    
    store.dispatch(action); 
  }

  handleItemDelete(index) { 
    
    const action = {
      type: DELETE_TODO_ITEM,  
      index 
    };
    
    store.dispatch(action); 
  } 

}

export default TodoList;

reducer.js 文件:

javascript 复制代码
// 3️⃣-③:引入"常量";
import {CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM} from "./actionTypes";  

const defaultState = { 
  inputValue: "", 
  list: []
};

// 3️⃣-④:用"常量"替换掉"字符串";
export default (state = defaultState, action) => { 
  
  if(action.type === CHANGE_INPUT_VALUE) {  
    
    const newState = JSON.parse(JSON.stringify(state)); 
  
    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 = ""; 
    
    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;
}

4️⃣查看下页面效果(正常运行):

❓5️⃣这样大费周章的好处是什么呢?

答: 在 TodoList.js 文件中,我们把 handleInputChange 方法里 type 对应的"常量 " CHANGE_INPUT_VALUE ,写成了 CHANGE_INPVT_VALUE

此时,程序就会给我们打印出清晰的"报错"信息:

如此一来,修改 bug 将变得特别简单!

祝好,qdywxs ♥ you!

相关推荐
cwj&xyp1 小时前
Python(二)str、list、tuple、dict、set
前端·python·算法
dlnu20152506221 小时前
ssr实现方案
前端·javascript·ssr
古木20191 小时前
前端面试宝典
前端·面试·职场和发展
轻口味3 小时前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王3 小时前
React Hooks
前端·javascript·react.js
迷途小码农零零发3 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀4 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪4 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef6 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端