欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

react+redux的升级版todoList的实现

程序员文章站 2022-04-23 16:59:38
又是很久不写博客了,最近在用蚂蚁金服的ant-design-pro写毕设,写着写着写不下去了,很多东西都不理解,不得不说大神写出来的东西都是需要花学习成本的,或者底子好,对...

又是很久不写博客了,最近在用蚂蚁金服的ant-design-pro写毕设,写着写着写不下去了,很多东西都不理解,不得不说大神写出来的东西都是需要花学习成本的,或者底子好,对于react新手来说就有点难了。所以就老老实实的认真看了下redux到底如何使用,在这里推荐一下自己最近在看的书,写的算是比较详细的:《深入react技术栈》。废话不多说,今天就分享下自己如何使用redux来实现一个todolist的,希望对想要用redux的你会有所帮助。

(为什么叫升级版呢?因为之前写过一个没有用redux的todolist

react+redux的升级版todoList的实现

该项目使用react官方的create-react-app架构,每个目录可以根据自己的需求来划分。下面解释下每个目录的内容和功能。

public:主要放静态资源(入口html文件,图片资源,json文件等);

src/component:不同的组件;

src/layouts:整个页面的基本架构,主要就是nav,footer,content。nav里面显示user和notice的数据,content中实现页面路由的切换,footer固定不变;

src/redux:

--src/redux/configurestore:生成整个应用的store;

--src/redux/reducers:所有reducer的集合;

src/routes:页面的整体路由;

src/utils:自己封装的工具;

views:存放项目中所要展示的所有页面;

index:整个项目的入口文件;

二. 具体实现

1. 整个应用中store中应存储什么数据?

const initialstate = {
  tasklistdata: { //任务列表
    loading: false,
    error: false,
    tasklist: [],
  }, 
  userdata: { //用户信息
    loading: false,
    error: false,
    user: {},
  },
  noticelistdata: { //通知列表
    loading: false,
    error: false,
    noticelist: [],
  },
  taskdata: { //任务详情,在详情页使用
    loading: false,
    error: false,
    task: {},
  }
};

2. reducer的分布:

每个state对应一个reducer,所以一共需要四个reducer,在src/redux/reducers中将所有的reducer合并,并且注意每个reducer的名字要和state同名:

/*redux/reducers.js*/
import { combinereducers } from 'redux';
import userreducer from '../component/user/indexredux';
import noticereducer from '../component/notice/indexredux';
import todolistreducer from '../views/todolist/indexredux';
import taskreducer from '../views/detail/indexredux';

export default combinereducers({
  userdata: userreducer,
  noticelistdata: noticereducer, 
  tasklistdata: todolistreducer,
  taskdata: taskreducer,
});

每个state都对应一个reducer,所以和state一样,reducer应在放在最*的父级组件的目录中,所以将tasklistdata的reducer放在src/views/todolist中,其他同理,代码如下:

/*views/todolist/indexredux.js*/
const tasklistdata = {
  loading: true,
  error: false,
  tasklist: []
};
//不同的action;
const load_tasklist = 'load_tasklist';
const load_tasklist_success = 'load_tasklist_success';
const load_tasklist_error = 'load_tasklist_error';
const add_task = 'add_task';
const update_task = 'update_task';
const delete_task = 'delete_task';
function todolistreducer (state = { tasklistdata }, action) {
  switch(action.type) {
    case load_tasklist: {
      return {
        ...state,
        loading: true,
        error: false,
      }
    }
    case load_tasklist_success: {
      return {
        ...state,
        loading: false,
        error: false,
        tasklist: action.payload,
      };
    }
    case load_tasklist_error: {
      return {
        ...state,
        loading: false,
        error: true
      };
    }
    case update_task: {
      const index = state.tasklist.indexof(
        state.tasklist.find(task => 
          task.id === action.payload.id));
      console.log(index);
      state.tasklist[index].status = !state.tasklist[index].status;
      return {
        ...state,
        tasklist: state.tasklist,
      };
    }
    case delete_task: {
      const index = state.tasklist.indexof(
        state.tasklist.find(task => 
          task.id === action.payload.id));
      state.tasklist.splice(index, 1);
      return {
        ...state,
        tasklist: state.tasklist,
      };
    }
    case add_task: {
      let len = state.tasklist.length;
      let index = len > 0 ? len - 1 : 0;
      let lasttaskid = index !== 0 ? state.tasklist[index].id : 0; 
      state.tasklist.push({
        id: lasttaskid + 1,
        name: action.payload.name,
        status: false,
      });
      return {
        ...state,
        tasklist: state.tasklist,
      }
    } 
    default: {
      return state;
    }
  }
}
export default todolistreducer;

3. action creator的分布:

每个动作都代表一个action,action由组件发出,所以将action creator单独一个文件,放在组件目录中。例如:listitem组件的action creator:

/*listitem/indexredux.js*/
//处理更新任务状态后和删除任务后的tasklist的状态;
const update_task = 'update_task';
const delete_task = 'delete_task';
//action creator,更新和删除任务
export function updatetask (task) {
  return dispatch => {
    dispatch({
      type: update_task,
      payload: task,
    });
  }
}
export function deletetask (task) {
  return dispatch => {
    dispatch({
      type: delete_task,
      payload: task,
    });
  }
}


三. 如何将redux和组件连接

react-redux提供了connect方法,将state和action creator绑在组件上,然后在组价内部以props的方式获取。下面是todolist页面的具体实现:

import react, { component } from 'react';
import { connect } from 'react-redux';
import { bindactioncreators } from 'redux';
import list from '../../component/list';
import { loadtasklist } from '../../component/list/indexredux';
import { updatetask, deletetask } from '../../component/listitem/indexredux';
import { addtask } from '../../component/submitdialog/indexredux';
class todolist extends component {

  render () {
    return (
      <list {...this.props} />
    );
  }
}
export default connect( state => {
  return {
    loading: state.tasklistdata.loading,
    error: state.tasklistdata.error,
    tasklist: state.tasklistdata.tasklist,
  };
}, dispatch => {
  return {
    loadtasklist: bindactioncreators(loadtasklist, dispatch),
    updatetask: bindactioncreators(updatetask, dispatch),
    deletetask: bindactioncreators(deletetask, dispatch),
    addtask: bindactioncreators(addtask, dispatch),
  };
})(todolist);

connect方法有四个参数,这里主要说下前两个参数:

(1)mapstatetoprops:参数为state,返回页面所需要的所有state;

(2)mapdispatchtoprops:参数为dispatch,返回页面所要使用的异步回调函数。

眼明手快的你肯定看到了,我们从redux包中导出了bindactioncreators方法,该方法将dispatch和action creator绑定,用来触发action。

四. 异步的action creator如何触发呢?

因为每个action creator都是异步函数,我们传给组件的只是函数的声明,所以就要引入我们的中间件,只用在生成store时加入就行了:

/*redux/configurestore.js*/
import { createstore, applymiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducers from './reducers';
const initialstate = {
  tasklistdata: {
    loading: false,
    error: false,
    tasklist: [],
  }, 
  userdata: {
    loading: false,
    error: false,
    user: {},
  },
  noticelistdata: {
    loading: false,
    error: false,
    noticelist: [],
  },
  taskdata: {
    loading: false,
    error: false,
    task: {},
  }
};
let enhancer = applymiddleware(thunk);
let store = createstore(
  reducers,
  initialstate,
  enhancer,
);
export default store;

在上面的代码中thunk就是一个中间件,我们将引入的中间件传入applymiddleware就可以了。

五. store在哪里传入组件呢?

我们肯定会想到,store在整个应用中都存在,所以应该在整个应用的最顶层,对于一般项目而言,当然就是最顶端的路由了:

import react, { component } from 'react';
import { browserrouter as router, route } from 'react-router-dom';
import { provider } from 'react-redux';
import basiclayout from '../layouts';
import store from '../redux/configurestore';
class routerapp extends component {
  render () {
    return (
      <provider store={store}>
        <router>
          <route path="/" component={basiclayout} />
        </router>
      </provider>
    );
  }
}
export default routerapp;


provider是react-redux的一个组件,作用就是用来将store传入整个应用。

基本要讲的就是这些内容,完整的项目请看 github
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。