(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!

相关推荐
Redstone Monstrosity7 分钟前
字节二面
前端·面试
东方翱翔14 分钟前
CSS的三种基本选择器
前端·css
Fan_web37 分钟前
JavaScript高级——闭包应用-自定义js模块
开发语言·前端·javascript·css·html
yanglamei19621 小时前
基于GIKT深度知识追踪模型的习题推荐系统源代码+数据库+使用说明,后端采用flask,前端采用vue
前端·数据库·flask
千穹凌帝1 小时前
SpinalHDL之结构(二)
开发语言·前端·fpga开发
dot.Net安全矩阵1 小时前
.NET内网实战:通过命令行解密Web.config
前端·学习·安全·web安全·矩阵·.net
叫我:松哥1 小时前
基于Python flask的医院管理学院,医生能够增加/删除/修改/删除病人的数据信息,有可视化分析
javascript·后端·python·mysql·信息可视化·flask·bootstrap
Hellc0071 小时前
MacOS升级ruby版本
前端·macos·ruby
前端西瓜哥1 小时前
贝塞尔曲线算法:求贝塞尔曲线和直线的交点
前端·算法
又写了一天BUG1 小时前
npm install安装缓慢及npm更换源
前端·npm·node.js