使用React-Redux编写TodoList

准备工作

TodoList组件

import React,{Component, Fragment} from 'react';
import 'antd/dist/antd.css';
import { Input,Button,List } from 'antd';
import { UserOutlined } from '@ant-design/icons';

class TodoList extends Component{
    render(){
        return (
            <Fragment>
                <div style={{marginTop:'10px',marginLeft:'10px'}}>
                    <Input size="large" placeholder="请输入..." prefix={<UserOutlined />} 
                        style={{width:'300px',marginRight:'10px'}}
                    />
                    <Button type="primary" style={{height:'39px'}}>提交</Button>
                </div>
                <List
                    style={{width:'300px',marginTop:'10px',marginLeft:'10px'}}
                    size="small"
                    bordered
                    dataSource={[]}
                    renderItem={(item) => <List.Item>{item}</List.Item>}
                />
            </Fragment>
        );
    }
}

export default TodoList;

挂载到页面上
在这里插入图片描述

./store/reducer.js
在这里插入图片描述

./store/index.js
在这里插入图片描述
在这里插入图片描述

OK~react-redux开始

首先安装react-redux

在入口文件中引入store以及react-redux的Provider组件

利用为Provider添加store属性之后,Provider下面的所有组件都可以连接store

import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList';
import {Provider} from 'react-redux';
import store from './store';

const App=(
  <Provider store={store}>
    <TodoList/>
  </Provider>
);

ReactDOM.render(App,document.getElementById('root'));


接下来到TodoList中去通过connect方法按照一定的规则(通过参数传递)连接store

connect方法可传递两个参数:mapStateToProps和mapDispatchToProps

export default connect(mapStateToProps,mapDispatchToProps)(TodoList);

mapStateToProps将store中的数据映射到当前组件的props中,这样一来,就可以直接通过this.props.list使用store中的list,inputValue同理

const mapStateToProps=(state)=>{
    return {
        value:state.inputValue,
        list:state.list
    }
}

在这里插入图片描述
这样便将store中的数据用到TodoList组件中啦
在这里插入图片描述

但是现在的输入框还不能输入,因此我们要为输入框绑定事件并传递action给store,再给reducer处理

此时事件处理函数就可以放在connect的第二个参数mapDispatchToProps中去写了

它作用是将store.dispatch方法映射到当前组件的props中,这样便可直接使用dispatch参数传递action

const mapDispatchToProps=(dispatch)=>{
    return {
        handleChange(e){
            const action={
                type:'handle_change',
                value:e.target.value
            }
            dispatch(action);
        }
    }
}

在这里插入图片描述

reducer处理数据

let func=(state=defaultState,action)=>{
    if(action.type==='handle_change'){
        const newState=JSON.parse(JSON.stringify(state));
        newState.inputValue=action.value;
        return newState;
    }
    return state;
}

现在输入框便可以输入内容了,这样就无需使用store.subscribe监听store的数据变化再做替换了
在这里插入图片描述
接下来也是同样的道理实现添加和删除功能,就不再多说啦

然后connect方法将todolist这个ui组件和数据和业务逻辑结合,返回的就是一个容器组件了

最后来做一些优化:定义actionTytpes、利用actionCreator统一创建action、对props对象解构赋值、由于组件只有一个render函数,把它处理成一个无状态组件,提升性能

TodoList.js

import React,{Fragment} from 'react';
import 'antd/dist/antd.css';
import { Input,Button,List } from 'antd';
import { UserOutlined } from '@ant-design/icons';
import {connect} from 'react-redux';
import {getChangeAction,getClickAction,getRemoveAction} from './store/actionCreator';

let TodoList=(props)=>{
    const {value,list,handleChange,handleClick,removeItem} =props;

    return (
        <Fragment>
            <div style={{marginTop:'10px',marginLeft:'10px'}}>
                <Input value={value} size="large" placeholder="请输入..." prefix={<UserOutlined />} 
                    style={{width:'300px',marginRight:'10px'}}
                    onChange={handleChange}
                />
                <Button type="primary" style={{height:'39px'}}
                    onClick={handleClick}
                >提交</Button>
            </div>
            <List
                style={{width:'300px',marginTop:'10px',marginLeft:'10px'}}
                size="small"
                bordered
                dataSource={list}
                renderItem={(item,index) => <List.Item onClick={()=>{
                    removeItem(index);
                }}>{item}</List.Item>}
            />
        </Fragment>
    );
}

const mapStateToProps=(state)=>{
    return {
        value:state.inputValue,
        list:state.list
    }
}

const mapDispatchToProps=(dispatch)=>{
    return {
        handleChange(e){
            const action=getChangeAction(e.target.value);
            dispatch(action);
        },

        handleClick(){
            const action=getClickAction();
            dispatch(action);
        },

        removeItem(index){
            const action=getRemoveAction(index);
            dispatch(action);
        }
    }
}

export default connect(mapStateToProps,mapDispatchToProps)(TodoList);

reducer.js

import {HANDLE_CHANGE,HANDLE_CLICK,REMOVE_ITEM} from './actionTypes';

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

let func=(state=defaultState,action)=>{
    if(action.type===HANDLE_CHANGE){
        const newState=JSON.parse(JSON.stringify(state));
        newState.inputValue=action.value;
        return newState;
    }
    if(action.type===HANDLE_CLICK){
        const newState=JSON.parse(JSON.stringify(state));
        newState.list.push(state.inputValue);
        newState.inputValue='';
        return newState;
    }
    if(action.type===REMOVE_ITEM){
        const newState=JSON.parse(JSON.stringify(state));
        newState.list.splice(action.value,1);
        return newState;
    }
    return state;
}

export default func;

效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值