调度功能不会“总是”更新道具

时间:2019-07-30 08:38:36

标签: reactjs redux react-redux redux-thunk

在我的示例待办事项列表应用程序中,我尝试在创建或删除待办事项之后更新所有待办事项,以便在更改后重新呈现列表组件。它有时会更新待办事项,但有时不会。我不知道原因。

我正在使用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容器上分派所有操作。

2 个答案:

答案 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}}