react-redux实现todolist增加删除功能,解决JavaScript事件绑定问题
1.创建TodoList组件
在react-redux中使用connect将组件和store做连接。mapStateToProps 会将state挂载到组件的props上,mapDispatchToProps 将store.dispatch方法挂在到props上,所以通过组件的props就可以得到状态和方法。由此可以发现TodoList实际上可以当做UI组件,而通过connect返回的是一个容器组件。
import React, { Component } from "react";
import { connect } from "react-redux";
class TodoList extends Component {
render() {
const {
inputValue,
list,
changeInputValue,
handleSubmit,
handleDel
} = this.props;
return (
<div>
<input value={inputValue} onChange={changeInputValue} />
<button onClick={handleSubmit}>添加</button>
<ul>
{list.map((item, index) => {
return (
<li
onClick={() => {
handleDel(index);
}}
key={index}
>
{item}
</li>
);
})}
</ul>
</div>
);
}
}
const mapStateToProps = state => {
return {
inputValue: state.inputValue,
list: state.list
};
};
const mapDispatchToProps = dispatch => {
return {
changeInputValue(e) {
const action = {
type: "change_value",
value: e.target.value
};
dispatch(action);
},
handleSubmit() {
const action = {
type: "add_item"
};
dispatch(action);
},
handleDel(index) {
const action = {
type: "delete_item",
value: index
};
dispatch(action);
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(TodoList);
事件绑定应注意的问题
在给li标签绑定事件时,出现了问题,直接给onClick绑定了handleDel方法,传入参数index,这样的写法其实没有给li绑定事件,而是只要渲染li标签就会执行handleDel事件,在reactjs中只要render()方法被执行就会执行此事件,正确的绑定事件的方法是通过绑定匿名函数,或者借助bind,如下第二种和第三种方式:
第一种:<li onClick={ handleDel(index) } key={index} > {item} </li>
第二种: <li onClick={() => {handleDel(index);}} key={index} > {item} </li>
第三种: <li onClick={ handleDel.bind(this,index) } key={index} > {item} </li>
2.创建store/index.js
import { createStore } from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
export default store;
3.创建store/reducer.js
const defaultValue = {
inputValue: "",
list: []
};
export default (state = defaultValue, action) => {
if (action.type === "change_value") {
const newState = JSON.parse(JSON.stringify(state));
newState.inputValue = action.value;
return newState;
}
if (action.type === "add_item") {
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue = "";
return newState;
}
if (action.type === "delete_item") {
const newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.value, 1);
return newState;
}
return state;
};
4.index.js文件引入react-redux中的Provider组件,传入store参数,那么在Provider中包含的组件都可以共享store参数。
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from "react-redux";
import store from "./store";
import TodoList from "./TodoList";
const APP = (
<Provider store={store}>
<TodoList />
</Provider>
)
ReactDOM.render(APP ,document.getElementById('root'));