转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥"前端一万小时"两大明星专栏------"从零基础到轻松就业"、"前端面试刷题",已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
javascript
涉及面试题:
1. 在 React 中如何定义常量?
2. Redux 中常量的用途是什么?
编号:[react_23]
1 为什么要拆分 actionTypes
紧接上一篇代码(请自行打开编辑器查看代码),我们可以很明显地看到:
-
在
TodoList.js
文件中,需要不断地派发action
。然后,每个action
又有一个type
,且对应一串"字符串"; -
在
reducer.js
文件中,reducer 接收action
的type
时,其"字符串"必须和TodoList.js
里type
对应的字符串"一模一样"!
这会带来什么问题呢?
我们在写代码的时候,偶尔会犯一些"笔误"。比如,在 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
文件里,将之前 action
中 types
属性对应的"字符串 "赋值给同名的"常量",并把这个"常量"导出。
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.js
和 reducer.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!