天天看點

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必須是一個純函數,源代碼