创建文件
这是一个经典的Redux模版,如果你对redux比较陌生,可以放弃使用 redux ,选择适合自己的代码习惯
此示例为基于Redux的高阶组件,如简单todolist可不遵循下方示例
- 在SRC文件夹中,创建一个新文件夹,这里示例
TODOLIST - 在
todolist下创建如下对应目录
│ todoPage.tsx //入口页面,内含todolist和子组件todoControl│ todoControl.tsx //操控组件│ todoList.tsx //列表控件│└─service //每个业务文件夹下必含该文件夹及其下属文件todoAction.ts //主要是功能处理todoReducers.ts //判断处理todoTypes.ts //内含有枚举,辅助reducer
书写代码
主要功能:从网络中获取现有todolist,并且赋予其增删功能(增删暂为本地)
确定好功能后,大概有这几种操作
export enum ETodoTypes {TODO_FETCH_LOADING = "TODO_FETCH_LOADING", //开始网络获取TODO_FETCH_SUCCESS = "TODO_FETCH_SUCCESS", //网络获取成功TODO_FETCH_ERROR = "TODO_FETCH_ERROR", //网络获取失败TODO_FETCH_REFUSH ="TODO_FETCH_REFUSH",TODO_ADD_ITEM = 'TODO_ADD_ITEM', //本地增加一条TODO_REMOVE_ITEM ='TODO_REMOVE_ITEM', //本地移除一条}
将他们书写在todoTypes.ts中,并将该文件引入 src/store/types/index.ts中,方便使用
export * from "../../todolist/service/todoTypes";
todoReducers.ts书写
引入刚刚写好的ETodoTypes和store目录下IInitialState
import { ETodoTypes, IInitialState } from "../../store/types";interface ITodo {userId: number,id: number,title: string,completed: boolean}interface INITSTATE {isLoading: boolean,todolist: Array<ITodo>}const initialState: INITSTATE = {isLoading: true,todolist: []};export const todoReducer = (state = initialState, action: IInitialState) => {switch (action.type) {case ETodoTypes.TODO_FETCH_LOADING:return {...state,isLoading: true};case ETodoTypes.TODO_FETCH_SUCCESS:return {...state,isLoading: false,todolist: action.payload as Array<ITodo>};case ETodoTypes.TODO_FETCH_REFUSH:return {...state,isLoading: false,todolist: action.payload as Array<ITodo>};case ETodoTypes.TODO_FETCH_ERROR:return {...state,isLoading: false,todolist: action.payload as Array<ITodo>};case ETodoTypes.TODO_ADD_ITEM:return {...state,isLoading: false,todolist: action.payload as Array<ITodo>};case ETodoTypes.TODO_REMOVE_ITEM:return {...state,isLoading: false,todolist: action.payload as Array<ITodo>};default:return state;}};
将该文件引入 src/store/reducers/index.ts中
export * from "../../todolist/service/todoReducers";
将写好的reducer引入/store/index.ts
import { createStore, combineReducers, applyMiddleware } from "redux";import thunkMiddleware from "redux-thunk";import { composeWithDevTools } from "redux-devtools-extension";import { userReducer,todoReducer } from "./reducers";// import { chatReducer } from "./chat/reducers";const rootReducer = combineReducers({user: userReducer,todo:todoReducer});export type AppState = ReturnType<typeof userReducer>;export const configureStore = () => {const middlewares = [thunkMiddleware];const middleWareEnhancer = applyMiddleware(...middlewares);const store = createStore(rootReducer,composeWithDevTools(middleWareEnhancer));return store;};
到这里,恭喜你,你已经完成了一大步,剩下的,就可以开心写代码了
接下来,我们在todoAction中为todoList书写三个功能
import { Dispatch } from "redux";import axios from "../../utils/http";import { ETodoTypes } from "../../store/types";import { IInitialState } from "../../store/types";export const getTodoList = () => async (dispatch: Dispatch<IInitialState>) => {dispatch({ type: ETodoTypes.TODO_FETCH_LOADING });try {const res = await axios.get(`http://jsonplaceholder.typicode.com/todos`);dispatch({ type: ETodoTypes.TODO_FETCH_SUCCESS, payload: res.data });} catch (error) {dispatch({ type: ETodoTypes.TODO_FETCH_ERROR });}};
todolist.tsx书写
我们知道它是由一个列表组成,那么我们引入antd中的列表组件,为他生成一个list
import React from "react";import { connect } from "react-redux";import { List, Button } from 'antd';import { getTodoList } from "./service/todoAction";import { AppState } from "../store";interface ITodoProps {state: AppState;getTodoList: () => void;}class TodoList extends React.Component<ITodoProps> {render() {console.log(this.props);const { state } = this.props;return <div><Listsize="small"borderedloading={state.todo.isLoading}dataSource={state.todo.todolist}renderItem={(item) => <List.Item>{item.title}<Button>删除</Button></List.Item>}/></div>;}componentDidMount() {this.props.getTodoList()}}const mapStateToProps = (state: AppState) => ({state});const mapDispatchToProps = (dispatch: any) => ({getTodoList: () => dispatch(getTodoList())});export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
看,他已经可以顺利加载数据了
接下来我们在每一条后面,增加一个删除按钮
在todoAction.ts中增加如下
export const removeItem = (todos: Array<any>, index: number) => (dispatch: Dispatch<IInitialState>) => {dispatch({ type: ETodoTypes.TODO_FETCH_LOADING });try {todos.splice(index, 1)dispatch({ type: ETodoTypes.TODO_REMOVE_ITEM, payload: todos });} catch (error) {dispatch({ type: ETodoTypes.TODO_FETCH_ERROR });}};
todoList的mapDispatchToProps中也增加相应的
removeItem: (todos: Array<any>, index: number) => dispatch(removeItem(todos, index))
在按钮中调用该方法即可
todoControl的书写
todoControl主要是有两个功能,一个是增加一条,一个是刷新列表
他独立于todoList,属于两个子组件通信,其实我写到这里,我也没有尝试过
让我们来一起试一下
todoControl中代码如下
import React, { Component } from 'react'import { connect } from 'react-redux';import { AppState } from '../store';import { addItem, refreshTodo } from './service/todoAction';import { Button } from 'antd';interface ITodoControlProps {state: AppState;refreshTodo: () => void;addItem: (todos: Array<any>) => void;}class TodoControl extends Component<ITodoControlProps>{render() {const { addItem, state, refreshTodo } = this.propsreturn (<div><Button onClick={refreshTodo}>刷新</Button><Button onClick={() => addItem(state.todo.todolist)}>随机添加</Button></div>)}}const mapStateToProps = (state: AppState) => ({state});const mapDispatchToProps = (dispatch: any) => ({addItem: (todos: Array<any>) => dispatch(addItem(todos)),refreshTodo: () => dispatch(refreshTodo()),});export default connect(mapStateToProps, mapDispatchToProps)(TodoControl);
todoAction
export const addItem = (todos: Array<any>) => (dispatch: Dispatch<IInitialState>) => {dispatch({ type: ETodoTypes.TODO_FETCH_LOADING });try {let item = {userId: Math.random(),id: Math.random(),title: `Title:${Math.random()}`,completed: false}todos.unshift(item)dispatch({ type: ETodoTypes.TODO_ADD_ITEM, payload: todos });} catch (error) {dispatch({ type: ETodoTypes.TODO_FETCH_ERROR });}};export const refreshTodo = () => async (dispatch: Dispatch<IInitialState>) => {dispatch({ type: ETodoTypes.TODO_FETCH_LOADING });try {const res = await axios.get(`http://jsonplaceholder.typicode.com/todos`);dispatch({ type: ETodoTypes.TODO_FETCH_SUCCESS, payload: res.data });} catch (error) {dispatch({ type: ETodoTypes.TODO_FETCH_ERROR });}};
Great! 完成!
