我正在学习React / Redux,并且遇到了困难。在我正在处理的todo应用程序示例中,当添加新的todo时,将执行addTodo操作,并且我可以逐步执行store.dispatch逻辑。失败的是hasStatePropsChanged值被计算为false因此没有子更新。
代码段如下:
import React from 'react';
import { connect } from 'react-redux';
import { store, addTodo, completeTodo, deleteTodo, clearTodo } from './TodoState.jsx';
class AddTodoForm extends React.Component {
...
}
class TodoItem extends React.Component {
....
}
let TodoList = ({items}) => (
<ul>
{items.map((item,index) =>
<TodoItem key={index} index={index} message={item.message} completed={item.completed}/>
)}
</ul>
)
let TodoComponent = ({ items, onAddTodo, onCompleteTodo, onDeleteTodo, onClearTodo }) => /* expand's props */
(
<div>
<h1>Todo</h1>
<AddTodoForm onAddTodo={onAddTodo} message/>
<TodoList items={items} onCompleteTodo={onCompleteTodo} onDeleteTodo={onDeleteTodo} onClearTodo={onClearTodo}/>
</div>
)
const mapStateToProps = (state) => {
return {
items: state.todo.items
}
}
const mapDispatchToProps = (dispatch) => {
return {
onAddTodo(message) {
dispatch(addTodo(message))
},
onCompleteTodo(index) {
dispatch(completeTodo(index))
},
onDeleteTodo(index) {
dispatch(deleteTodo(index))
},
onClearTodo(index) {
dispatch(clearTodo(index))
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(TodoComponent);
AddTodoForm正确调度addTodo动作,问题是TodoList组件即使通过items数组再次渲染也是一个新数组。
更新: 我的减速机确实恢复了新的状态。
这是减速器和动作代码:
import { createStore } from 'redux';
var defaultState = { todo: { items: [] } }
const ADD_TODO = 1;
const COMPLETE_TODO = 2;
const DELETE_TODO = 3;
const CLEAR_TODO = 4;
const addTodo = (message) => { return {type: ADD_TODO, message: message, completed: false} };
const completeTodo = (index) => { return {type: COMPLETE_TODO, index:index} };
const deleteTodo = (index) => { return {type: DELETE_TODO, index:index} };
const clearTodo = (index) => { return {type: CLEAR_TODO, index:index} };
function todoReducer(state,action) {
switch(action.type) {
case ADD_TODO:
var newState = Object.assign({},state);
newState.todo.items.push({message:action.message,completed:false});
return newState;
case COMPLETE_TODO:
var newState = Object.assign({},state);
newState.todo.items[action.index].completed = true;
return newState;
case DELETE_TODO:
var items = [].concat(state.todo.items);
items.splice(action.index,1);
return Object.assign({},state,{
todo: {
items:items
}
});
case CLEAR_TODO:
return Object.assign({},state,{
todo: {
items: []
}
});
default:
return state;
}
}
var store = createStore(todoReducer,defaultState);
export { store, addTodo, completeTodo, deleteTodo, clearTodo };
谢谢,
亚伦
答案 0 :(得分:2)
检查是否将新对象作为reducer中的状态返回。
例如:
return Object.assign ({}, state, {items: [...oldItems, newItem]})
注意[...oldItems, newItem]
这将创建新阵列。在您的情况下,Object.assign只执行浅拷贝,实际上项目已更改,但保留相同的引用。看看工作示例:
import React from 'react';
import { render } from 'react-dom';
import { connect, Provider } from 'react-redux';
import { createStore } from 'redux';
var defaultState = { todo: { items: [] } }
const ADD_TODO = 1;
const COMPLETE_TODO = 2;
const DELETE_TODO = 3;
const CLEAR_TODO = 4;
const addTodo = (message) => { return {type: ADD_TODO, message: message, completed: false} };
const completeTodo = (index) => { return {type: COMPLETE_TODO, index:index} };
const deleteTodo = (index) => { return {type: DELETE_TODO, index:index} };
const clearTodo = (index) => { return {type: CLEAR_TODO, index:index} };
function todoReducer(state,action) {
switch(action.type) {
case ADD_TODO:
var newItem = {message:action.message,completed:false};
return Object.assign({},state, {todo: {items: [...state.todo.items, newItem]}});
case COMPLETE_TODO:
var newState = Object.assign({},state);
newState.todo.items[action.index].completed = true;
return newState;
case DELETE_TODO:
var items = [].concat(state.todo.items);
items.splice(action.index,1);
return Object.assign({},state,{
todo: {
items:items
}
});
case CLEAR_TODO:
return Object.assign({},state,{
todo: {
items: []
}
});
default:
return state;
}
}
var store = createStore(todoReducer,defaultState);
class AddTodoForm extends React.Component {
render() {
return <button onClick={this.props.onAddTodo}>test</button>
}
}
class TodoItem extends React.Component {
render() {
return <span>item</span>
}
}
let TodoList = ({items}) => (
<ul>
{items.map((item,index) =>
<TodoItem key={index} index={index} message={item.message} completed={item.completed}/>
)}
</ul>
)
let TodoComponent = ({ items, onAddTodo, onCompleteTodo, onDeleteTodo, onClearTodo }) => /* expand's props */
(
<div>
<h1>Todo</h1>
<AddTodoForm onAddTodo={onAddTodo} message/>
<TodoList items={items} onCompleteTodo={onCompleteTodo} onDeleteTodo={onDeleteTodo} onClearTodo={onClearTodo}/>
</div>
)
const mapStateToProps = (state) => {
return {
items: state.todo.items
}
}
const mapDispatchToProps = (dispatch) => {
return {
onAddTodo(message) {
dispatch(addTodo(message))
},
onCompleteTodo(index) {
dispatch(completeTodo(index))
},
onDeleteTodo(index) {
dispatch(deleteTodo(index))
},
onClearTodo(index) {
dispatch(clearTodo(index))
}
}
}
var Wrapper = connect(mapStateToProps,mapDispatchToProps)(TodoComponent);
render(
<Provider store={store}>
<Wrapper />
</Provider>,
document.getElementById('app')
)