React 16 學習筆記(一)使用 Redux react-redux TodoList
使用create-react-app建立React項目
在指定目錄使用如下指令建立項目todolist
create-react-app todolist
安裝redux
yarn add redux
安裝react-redux
yarn add react-redux
修改目錄
剔除不需要的檔案如圖:
建立存儲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必須是一個純函數,源代碼