使用Redux axios完成TodoList 列表的网络请求初始化、增加、删除功能

本文介绍了如何使用Redux和axios在React中实现TodoList的网络请求功能,包括初始化、添加和删除任务。通过触发action,执行reducer更新state,再通过connect方法将state和actions绑定到组件,实现UI的自动更新。源码可在GitHub找到。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. git 源码 https://github.com/fanxiao168/React-todoList

  2. 效果图
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

先说下上图他们之间是怎么操作流通的:
1、当view需要发起行为时,需要在当前位置触发action,即store.dispatch(addNote())
2、当Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。而这种 State 的计算过程就叫做 Reducer。而Reducer方法是由store.dispatch方法触发来自动执行的。为此,Store 需要知道 Reducer 函数,做法就是在生成 Store 的时候,将 Reducer 传入createStore方法。
import { createStore } from ‘redux’; const store = createStore(reducer);
Reducer 是一个函数,且为纯函数,它接受 Action 和当前 State 作为参数,Reducer 函数里面不能改变 State,必须返回一个全新的state对象。
3、state更新,触发view发生改变,而在此之前必须把数据store和操作事件action绑定到需要使用的组件上,就需要用到connect函数(connect方法可参考这篇文章:https://yq.aliyun.com/articles/59428):
意思是先接受两个参数(数据绑定mapStateToProps和事件绑定mapDispatchToProps),再接受一个参数(将要绑定的组件本身):
export default connect(mapStateToProps,mapDispatchToProps)(App)
其中:
mapStateToProps 就是将state作为props绑定到组件上
mapDispatchToProps是可选的,将 action 作为 props 绑定到组件上,如果不传这个参数redux会把dispatch作为属性注入给组件,可以手动当做store.dispatch使用
//mapDispatchToProps 为actions里面的函数绑定dispatch,可直接调用this.props.actions.xxx(),即等同于没绑定情况下this.props.dispatch(xxx()),不需要手动dispatch
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators(actions, dispatch)
});
//mapStateToProps 可返回当前数组需要的几个state属性值
const mapStateToProps = state => {
return{
notes : state.notes
}
};
以上,便可以在组件内触发action,更新state,来更新view的变化

在这里插入图片描述
3. 创建store store文件夹下 index.js

import { createStore ,applyMiddleware ,compose} from 'redux';
import reducer from './reducer';
import thunk from 'redux-thunk';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;

const enhancer = composeEnhancers(
  applyMiddleware(thunk)
);
const store = createStore(reducer, enhancer);


export default store;
  1. 编写action

定义action事件 actionTypes.js

export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DELETE_TODO_ITEM = 'delete_todo_item';
export const INIT_LIST_ACTION = 'init_list_action';

actionCreators.js

import { INIT_LIST_ACTION , CHANGE_INPUT_VALUE , ADD_TODO_ITEM , DELETE_TODO_ITEM} from './actionTypes';
import axios from 'axios';

export const getInputChangeAction = (value) => ({
	type: CHANGE_INPUT_VALUE,
	value
});

export const getAddItemAction = () => ({
	type: ADD_TODO_ITEM
});

export const getDeleteItemAction = (index) => ({
	type: DELETE_TODO_ITEM,
	index
});

export const getInitListAction = (data) => ({
	type: INIT_LIST_ACTION,
	data
});

export const getTodoList = () => {
	return (dispatch) => {
		axios.get('/list.json')
			.then((res) => {
				const data = res.data;
				const action = getInitListAction(data);
				dispatch(action);
			})
			.catch(() => {
				alert('error')
			});
	}
}

编写reducer.js

import { CHANGE_INPUT_VALUE ,ADD_TODO_ITEM , DELETE_TODO_ITEM ,INIT_LIST_ACTION } from './actionTypes';

const defaultState = {
	inputValue: '',
	list: []
}

//reducer 可以接收state, 但是绝对不能修改state
//纯函数指的是,给定固定的输入,就一定会有固定的输出,而且不会有任何副作用
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 === INIT_LIST_ACTION) {
		const newState = JSON.parse(JSON.stringify(state));
		console.log(action.data);
		newState.list = action.data;
		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;
}

入口目录index.js

import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList';

ReactDOM.render(<TodoList />, document.getElementById('root'));

TodoList.js

import React, { Component } from 'react';
import 'antd/dist/antd.css'; 
import TodoListUI from './TodoListUI';
import store from './store'
import { getInputChangeAction ,getAddItemAction , getDeleteItemAction , getTodoList} from './store/actionCreators';


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.handleItemDelete = this.handleItemDelete.bind(this);
		store.subscribe(this.handleStoreChange);
		}
	render(){
		return (
			
			<TodoListUI
				inputValue={this.state.inputValue}
				list={this.state.list}
				handleInputChange={this.handleInputChange}
				handleBtnClick={this.handleBtnClick}
				handleItemDelete={this.handleItemDelete}
			/>

			)
	}

	componentDidMount() {
		const action = getTodoList();
		store.dispatch(action);
	}

	handleInputChange(e){
		const action = getInputChangeAction(e.target.value);
		store.dispatch(action);
	}

	handleStoreChange(){
		this.setState(store.getState());
	}

	handleBtnClick(){
		const action = getAddItemAction();
		store.dispatch(action);
	}

	handleItemDelete(index){
		const action = getDeleteItemAction(index);
		store.dispatch(action);
	}
}

export default TodoList;

UI组件TodoListUI.js

import React from 'react';
import { Input , Button , List  } from 'antd';

//无状态组件:当一个组件只含有render函数时,可以考虑使用无状态组件;
//无状态组件的性能要优于普通组件
const  TodoListUI = (props) => {

	return (
			<div style={{marginTop:'10px',marginLeft:'10px'}}>
				<div>
					<Input 
					 	value={props.inputValue} 
					 	placeholder="todo info"  
					 	style={{width:'300px',marginRight:'10px'}}
					 	onChange={props.handleInputChange}
					 	/>
					<Button type="primary" onClick={props.handleBtnClick}>提交</Button>
				</div>

				<List 
					style={{width:'300px', marginTop:'10px'}}
					bordered
				    dataSource={props.list}
				    renderItem={(item,index) => (<List.Item onClick={ () => {props.handleItemDelete(index)}} key={item} >{item}</List.Item>)}
			  	/>

			</div>
		)
}

export default TodoListUI;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值