我正在尝试制作一个todo应用程序来学习React Redux。 我的状态是这样的
[
{
taskName:"ABS",
status: true
},
{
taskName:"XYZ",
status: false
}
]
基本上,每个任务都是一个对象。我想在每次按下按钮时切换特定任务的状态(它在红色和绿色之间改变颜色),所以我设计我的减速器如下:
尝试1:
var stateClone = [...state];
stateClone[action.index].status = !stateClone[action.index].status;
return stateClone;
尝试2:
var cloneTask = {...state[action.index]}
cloneTask.status = !cloneTask.status;
state[action.index] = cloneTask
localStorage.setItem('tasks', JSON.stringify(state));
return [...state];
据我了解,两者都是纯粹的功能。两者都返回正确的状态,但只有尝试2成功更新了视图,尝试1确实更新了状态,但没有正确更新视图。
有人帮助我。谢谢!
**
import React, { Component } from 'react';
import TaskItem from './TaskItem';
import { connect } from 'react-redux'
class TaskList extends Component {
constructor(props){
super(props);
this.state = {
filterName: '',
filterStatus: -1
};
}
onChange = (event)=>{
var target = event.target;
var name = target.name;
var value = target.value;
console.log(name)
this.props.onFilter(name==='filterName'?value:this.state.filterName,
name==='filterStatus'?value:this.state.filterStatus);
this.setState({
[name]:value
});
}
render() {
// console.log(this.props);
var { tasks } = this.props;
var { filterName, filterStatus } = this.state;
var elemTask = tasks.map((item, index)=>{
return <TaskItem
key={index+1}
item={item}
index={index}
deleteTask={this.props.deleteTask}
editTask = {this.props.editTask}
/>
});
return (
<table className="table table-bordered table-hover mt-15">
<thead>
<tr>
<th className="text-center">STT</th>
<th className="text-center">Task</th>
<th className="text-center">Status</th>
<th className="text-center">Action</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>
<input
type="text"
className="form-control"
name="filterName"
value={filterName}
onChange={this.onChange}
/>
</td>
<td>
<select name="filterStatus"
value={filterStatus}
className="form-control"
onChange={this.onChange}>
<option value={-1}>All</option>
<option value={0}>OnHold</option>
<option value={1}>Active</option>
</select>
</td>
<td></td>
</tr>
{elemTask}
</tbody>
</table>
);
}
}
const mapStateToProps = (state) => {
return {
tasks: state.tasks
};
}
export default connect(mapStateToProps, null)(TaskList);
**
我应该从商店获取状态的反应文件
import * as types from '../constants/ActionTypes';
var data = JSON.parse(localStorage.getItem('tasks'));
var initialState = data? data: [];
var myReducer = (state=initialState, action) => {
switch(action.type){
case types.LIST_ALL:
return state;
case types.ADD_TASK:
var newTask = {
id: Math.random(),
name: action.task.name ,
status: action.task.status==='true'
}
state.push(newTask);
localStorage.setItem('tasks', JSON.stringify(state));
return [...state];
case types.UPDATE_STATUS:
// var stateClone = [...state];
// stateClone[action.index].status = !stateClone[action.index].status;
// console.log(stateClone);
// return stateClone;
var cloneTask = {...state[action.index]}
cloneTask.status = !cloneTask.status;
state[action.index] = cloneTask
localStorage.setItem('tasks', JSON.stringify(state));
console.log(state);
return [...state];
default: return state
}
};
export default myReducer;
答案 0 :(得分:3)
在这两种情况下,你改变状态。
首先,复制对象,然后更改其中一个; React看到相同的对象,并认为没有任何改变。
在第二个中,您创建一个新对象,但将其放在现有数组中。 React看到的阵列仍然相同,并认为没有任何变化。
您需要返回一个新数组,并为已更改的数组添加新对象。
这样做的一种方法是基本上结合你的两次尝试:
var stateClone = [...state];
var cloneTask = {...state[action.index]};
cloneTask.status = !cloneTask.status;
stateClone[action.index] = cloneTask;
return stateClone;
应该工作。