天天看点

React 16 学习笔记(一)使用 Redux react-redux TodoList使用create-react-app创建React项目创建存储store修改index.js创建TodoList.js修改input框value属性输入的数据存入list,并显示添加点击删除功能代码优化总结

React 16 学习笔记(一)使用 Redux react-redux TodoList

使用create-react-app创建React项目

在指定目录使用如下命令创建项目todolist

create-react-app todolist
           

安装redux

yarn add redux
           
React 16 学习笔记(一)使用 Redux react-redux TodoList使用create-react-app创建React项目创建存储store修改index.js创建TodoList.js修改input框value属性输入的数据存入list,并显示添加点击删除功能代码优化总结

安装react-redux

yarn add react-redux
           
React 16 学习笔记(一)使用 Redux react-redux TodoList使用create-react-app创建React项目创建存储store修改index.js创建TodoList.js修改input框value属性输入的数据存入list,并显示添加点击删除功能代码优化总结

修改目录

剔除不需要的文件如图:

React 16 学习笔记(一)使用 Redux react-redux TodoList使用create-react-app创建React项目创建存储store修改index.js创建TodoList.js修改input框value属性输入的数据存入list,并显示添加点击删除功能代码优化总结

创建存储store

创建一个store目录,store中创建两个文件index,js和reducer.js

reducer.js

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

export default (state=defaultState, action) => {
    return state
}
           

index.js

import { createStore } from "redux";
import reducer from "./reducer";

const store = createStore(reducer);

export default store;
           

修改index.js

Provider 功能是使被 包裹的TodoList组件使用react-redux

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

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

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



           

创建TodoList.js

class TodoList extends Component{
    render() {
        return (
            <Fragment>
                <input />
                <button>提交</button>
            </Fragment>
        )
    }
}

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

const mapDispatchToProps=(dispatch)=>{
    return {
        
    }
};

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

修改input框value属性

input 值定义为inputValue,onChang事件,绑定一个InputChange方法

<input value={inputValue} onChange={this.props.InputChange}/>
           

在mapDispatchToProps中构造InputChange方法

这里需要定义一个type,用于区别传递的是哪个方法的action,通过 dispatch(action);直接将action传递给reducer

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

    }
};
           

reducer接受传送过来的action

reducer不能直接修改store,因此需要先深拷贝一份store中的state,newState 中的inputValue修改后,将newState返回给store,store自动修改自己的数据

reducer.js

export default (state = defaultState, action) => {
    if (action.type === 'CHANGE_INPUT_VALUE') {
        const newState = JSON.parse(JSON.stringify(state)); // 拷贝一份
        newState.inputValue = action.value;
        return newState;
    }
    return state
}
           

输入的数据存入list,并显示

将上一步骤已修改的inputValue值,通过点击按钮,添加到list中。list通过map()方法循环显示在页面上

为按钮点击事件绑定方法

<button onClick={this.props.handleClick}>提交</button>
           

在mapDispatchToProps中构造handleClick方法

这里只需要传递一个type给reducer就可以了,不需要再讲inputValue进行传递,因为上步骤中已经修改好store中inputValue的值,直接使用就可以

handleClick(){
            const action={
                type: 'CLICK_BUTTON',
            };
            dispatch(action);
        },
           

reducer接受传送过来的action

if (action.type === 'CLICK_BUTTON') {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.push(newState.inputValue);
        newState.inputValue = '';//起到清空页面input框输入值
        return newState;
    }
           

页面显示list中的数据

map需要一个key值,使用index;

{
                    this.props.list.map((item,index)=>{
                        return (
                            <li key={index} >{item}</li>
                        )
                    })
                }
           

添加点击删除功能

删除list中的某个值,需要知道这个值所对应的下标,需要将index传递给一个方法。bind()可以向方法传递参数,但是参数不能是第一个位置。,为li标签绑定一个点击事件,通过bind()给方法传递index参数

li标签绑定事件方法

<li key={index} onClick={deleteItem.bind(this,index)}>{item}</li>
           

在mapDispatchToProps中构造deleteItem方法

deleteItem(index){
            const action={
                type:'DELETE_ITEM',
                index
            };
            dispatch(action);
        },
           

reducer接受传送过来的action

splice删除对应index的list元素

if (action.type === 'DELETE_ITEM') {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.splice(action.index,1);
        return newState;
    }
           

代码优化

优化主要在两个方面:

一、todolist组件中不含有复杂逻辑,只有一个render()函数,改写为UI组件

二、ActionTypes进行拆分

首先拆分ActionTypes,创建actionTypes.js,需要对TodoList.js 和reducer.js进行修改

export const CHANGE_INPUT_VALUE = 'change_input_value';
export const CLICK_BUTTON = 'click_button';
export const DELETE_ITEM = 'delete_item';

           

TodoIist.js

import React,{ Fragment } from 'react';
import { connect } from 'react-redux';
import {CHANGE_INPUT_VALUE,CLICK_BUTTON,DELETE_ITEM} from './store/actionTypes'

const TodoList= (props)=>{
    const {inputValue,handleInputChange,handleClick,list,deleteItem} = props;
    return (
        <Fragment>
            <input value={inputValue} onChange={handleInputChange}/>
            <button onClick={handleClick}>提交</button>
            {
                list.map((item,index)=>{
                    return (
                        <li key={index} onClick={deleteItem.bind(this,index)}>{item}</li>
                    )
                })
            }
        </Fragment>
    )
};

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

const mapDispatchToProps=(dispatch)=>{
    return {
        handleInputChange(e) {
            const action = {
                type:CHANGE_INPUT_VALUE,
                value:e.target.value
            };
            dispatch(action);
        },
        handleClick(){
            const action={
                type: CLICK_BUTTON,
            };
            dispatch(action);
        },
        deleteItem(index){
            const action={
                type:DELETE_ITEM,
                index
            };
            dispatch(action);
        },
    }
};

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

总结

到此完成了全部代码,Redux需要注意:reducer不能直接修改store中的数据,需要先深拷贝,修改,再返回给store,同时reducer必须是一个纯函数,源代码