在我的示例待办事项列表应用程序中,我尝试在创建或删除待办事项之后更新所有待办事项,以便在更改后重新呈现列表组件。它有时会更新待办事项,但有时不会。我不知道原因。
我正在使用Redux和Thunk。单击按钮时,我调度“创建请求”,然后发出异步请求,然后调度“创建收到”,然后调度fetchAllTodos()
,然后捕获“创建失败”。
在HomePage
容器中,我将this.props.todos
传递给TodoList
组件作为道具。我的问题是它有时会随更改重新呈现列表组件,但有时却不会。我还发现在componentWillReceiveProps
方法中我没有得到更新的道具。这可能与服务器问题有关,还是我做错了什么?
这是我开设商店的方式:
const middlewares = [thunk];
const store = createStore(
combineReducers({
...reducers,
}),
compose(applyMiddleware(...middlewares))
);
这是fetchAllTodos()
方法:
export function fetchAllTodos() {
return dispatch => {
dispatch({
type: ALL_TODOS_REQUESTED
});
console.log('todos requested');
return SuperFetch.get('/todos')
.then(todos => {
console.log('todos received ' + todos.length);
dispatch({
type: ALL_TODOS_RECEIVED,
payload: todos
})
})
.catch(error => dispatch({
type: ALL_TODOS_FAILED,
payload: error
}));
}
这是createTodo()
方法:
export function createTodo(description) {
const body = {description: description};
return dispatch => {
dispatch({
type: CREATE_TODO_REQUESTED
});
return SuperFetch.post(`/todos`, body)
.then(todo => dispatch({
type: CREATE_TODO_RECEIVED,
payload: todo
}))
.then(dispatch(fetchAllTodos()))
.catch(error => dispatch({
type: CREATE_TODO_FAILED,
payload: error
}));
}
}
这是减速器:
export default function todoReducer(state = initialState, action) {
switch (action.type) {
case ALL_TODOS_REQUESTED:
state = Object.assign({}, state, {todosLoading: true, todosError: null});
break;
case ALL_TODOS_RECEIVED:
state = Object.assign({}, state, {todos: action.payload, todosLoading: false, todosError: null});
break;
case ALL_TODOS_FAILED:
state = Object.assign({}, state, {todos: null, todosLoading: false, todosError: action.payload});
break;
// rest of it
return state
在HomePage
中,我只是将状态映射到道具,然后将待办事项(如果它们存在)传递给他们:
render() {
const {todos, error, loading} = this.props;
// if error part
if (todos && !loading) {
return (
<React.Fragment>
<Container text>
<TodoInput/>
</Container>
<Container style={{marginTop: '1em'}} text>
<TodoList todos={todos}/>
</Container>
</React.Fragment>
);
}
该问题可能与我在TodoInput
组件中分派操作并尝试更新TodoList
的事实有关吗?如果是这样,该如何解决该问题,因为我不想在同一HomePage
容器上分派所有操作。
答案 0 :(得分:0)
问题在于您在化简器中管理状态的方式。您所做的是通过执行state = blah
来直接改变现有状态,这违反了redux-priniciples。为了使redux
有效地识别出对reducer的更改,您必须return
一个全新的状态对象。只有这样,您的连接组件才会使用更新的reducer数据重新渲染。
export default function todoReducer(state = initialState, action) {
switch (action.type) {
case ALL_TODOS_REQUESTED:
return {
...state,
todosLoading: true,
todosError: null
}
case ALL_TODOS_RECEIVED:
return {
...state,
todos: action.payload,
todosLoading: false,
todosError: null
}
case ALL_TODOS_FAILED:
return {
...state,
todos: null,
todosLoading: false,
todosError: action.payload
}
default:
return state
}
}
答案 1 :(得分:0)
问题是如何在化简器中更新状态:
如果待办事项是对象
state = {...state, {todos: {...action.payload, ...state.todos }, todosLoading: false, todosError: null}}
如果待办事项在列表中
state = {...state, {todos: state.todos.concat(action.payload) }, todosLoading: false, todosError: null}}