Redux 入门
使用 Redux 重构之前的 TodoList,使用全局 state 来实现。
Redux Flow
Redux 的工作流:
一、引入依赖
需要先引入 Ant Design 和 Redux
yarn add antd
yarn add redux
二、创建全局 Store
第一步:创建 store/reducer.js
reducer 必须返回一个函数,state 参数为存储的内容
const defaultState = {
// state默认值
inputValue: "123",
list: [1, 2, 3]
};
export default (state = defaultState, action) => {
return state;
};
第二步:创建 store/index.js
使用 redux 的 createStore 方法,使用之前创建的 reducer 作为参数,创建一个 store
import { createStore } from "redux";
import reducer from "./reducer";
const store = createStore(reducer);
export default store;
使用与修改
一:使用 redux 的公共存储
import store from "./store/index.js";
// import store from './store' // 可以缩写为这样
console.log(store.getState()); // 直接能打印出store中的内容
二:修改 redux 中的内容
注意:redux 的 reducer 只支持读取 state,而不支持修改 state。如果需要修改,请深拷贝原有 state,修改新的 newState,并将 newState 返回。
const defaultState = {
inputValue: "Hello React !",
list: ["1111", "2222"]
};
export default (state = defaultState, action) => {
if (action.type === "change_input_value") {
const newState = JSON.parse(JSON.stringify(state));
newState.inputValue = action.value;
return newState;
} else if (action.type === "add_list_item") {
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(state.inputValue);
newState.inputValue = "";
return newState;
} else if (action.type === "del_list_item") {
const newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.index, 1);
return newState;
}
return state;
};
三、监听 store 内容的修改
constructor(props) {
super(props);
this.state = store.getState();
this.handleStoreChange = this.handleStoreChange.bind(this);
store.subscribe(this.handleStoreChange);
}
render () {
...
}
handleStoreChange() {
this.setState(store.getState());
}
整体使用如下:
src/TodoList.js
import React, { Component } from "react";
import store from "./store";
import "antd/dist/antd.css";
import { Input, Button, List } from "antd";
import {
getInputChangeAction,
getAddItemAction,
getDeleteItemAction
} from "./store/actionCreator";
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);
this.handleDeleteItem = this.handleDeleteItem.bind(this);
store.subscribe(this.handleStoreChange);
}
render() {
return (
<div style={{ marginTop: "10px", marginLeft: "10px" }}>
<Input
style={{ width: "300px", marginRight: "10px" }}
value={this.state.inputValue}
onChange={this.handleInputChange}
/>
<Button type="primary" onClick={this.handleBtnClick}>
�交
</Button>
<br />
<List
style={{ width: "300px" }}
bordered
dataSource={this.state.list}
renderItem={(item, index) => (
<List.Item onClick={() => this.handleDeleteItem(index)}>
{item}
</List.Item>
)}
/>
</div>
);
}
handleInputChange(e) {
const value = e.target.value;
const action = getInputChangeAction(value);
store.dispatch(action);
}
handleStoreChange() {
this.setState(store.getState());
}
handleBtnClick() {
const action = getAddItemAction();
store.dispatch(action);
}
handleDeleteItem(index) {
const action = getDeleteItemAction(index);
store.dispatch(action);
}
}
export default TodoList;
src/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;
src/store/reducer.js
const defaultState = {
inputValue: "Hello React !",
list: ["1111", "2222"]
};
export default (state = defaultState, action) => {
if (action.type === "change_input_value") {
const newState = JSON.parse(JSON.stringify(state));
newState.inputValue = action.value;
return newState;
} else if (action.type === "add_list_item") {
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(state.inputValue);
newState.inputValue = "";
return newState;
} else if (action.type === "del_list_item") {
const newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.index, 1);
return newState;
}
return state;
};
src/store/actionTypes.js
将所有的 Action 类型提取为常量,统一管理。方便调试与代码定位。
export const CHANGE_INPUT_VALUE = "change_input_value";
export const ADD_LIST_ITEM = "add_list_item";
export const DEL_LIST_ITEM = "del_list_item";
src/store/actionCreator.js
将 Action 的创建统一管理,使用 Creator 提供创建 Action 的方法。使流程更加清晰
import {
CHANGE_INPUT_VALUE,
ADD_LIST_ITEM,
DEL_LIST_ITEM
} from "./actionTypes";
export const getInputChangeAction = value => ({
type: CHANGE_INPUT_VALUE,
value: value
});
export const getAddItemAction = () => ({
type: ADD_LIST_ITEM
});
export const getDeleteItemAction = index => ({
type: DEL_LIST_ITEM,
index: index
});