0

我对编码很陌生,我目前正在练习useReducer()React 中的钩子,以在一个简单的待办事项应用程序中管理一些状态。尝试实施 TOGGLE_TODO 操作时遇到问题。我在使用数组之前已经完成了它,但是由于我可能会使用很多对象,所以我试图弄清楚为什么我不能做到这一点。我会说我正在通过失败来学习,但我正在学习的只是如何关闭计算机并走开!

每次切换时,我都会使用扩展运算符传递状态,我已经在所有项目中尝试过,我已经注销keyaction.payload确保我得到匹配(当我执行带有匹配的简单警报)。

我知道切换还不是切换,我只是想简单complete地成为true.

我尝试了很多方法来返回状态,我已经在语句的开头添加了返回,并且在此过程中我遇到了一些奇怪的错误。如前所述,目前这是非常简单的状态,但它会在我正在处理的另一个项目中更复杂,所以 useState 变得非常混乱。

对我在这里做错的任何帮助将不胜感激。

const initialAppState = {
  isOpen: true,
  todos: {}
};

export const ACTIONS = {
  TOGGLE_MODAL: "toggle-modal",
  ADD_TODO: "add-todo",
  TOGGLE_TODO: "toggle-todo"
};

const reducer = (state, action) => {
  // switch statement for actions
  switch (action.type) {
    case ACTIONS.TOGGLE_MODAL:
      return { ...state, isOpen: !state.isOpen };
    case ACTIONS.ADD_TODO:
      return {
        ...state,
        todos: {
          ...state.todos,
          // Object is created with Unix code as the key
          [Date.now()]: {
            todo: action.payload.todo,
            complete: false
          }
        }
      };
    case ACTIONS.TOGGLE_TODO:
      // Comparing the key and the action payload. If they match, it should set complete to 'true'. This will be updated to a toggle when working. 
      Object.keys(state.todos).map((key) => {
        if (key === action.payload) {
          return {
            ...state,
            todos: { ...state.todos, [key]: { complete: true } }
          };
        }
        return state;
      });
    default:
      throw new Error("Nope. not working");
  }
};

在渲染中,我将它key作为一个传递,id因此它可以与有效负载一起返回。这是dispatch组件的功能...

const Todo = ({ id, value, dispatch }) => {
  return (
    <div className="todo">
      <h1>{`Todo: ${value.todo}`}</h1>
      <p>Done? {`${value.complete}`}</p>
      <button
        onClick={() =>
          dispatch({
            type: ACTIONS.TOGGLE_TODO,
            payload: id
          })
        }
      >
        Mark as Done
      </button>
    </div>
  );
};

并且渲染正在使用Object.entries,一切正常。有时我会遇到错误,或者初始todo状态会消失,所以我知道状态没有正确更新。

这里也是CodeSandbox 上的代码。如果我让它工作,我会在这里更新,但我已经被困在这里几天了。:-(

4

1 回答 1

0

你快到了,用 Date.now() 索引你的项目是个好主意!
TOGGLE_TODO 案例中只有几个问题:

  • 你的reducer应该总是返回一个状态,你的return语句应该在case的结尾,但是你把它和map的函数放在一起
  • 你的 reducer 应该计算一个新的状态,而不是改变当前的状态。因此,您必须创建一个具有完整属性的新 todo 对象。

这是怎么回事:

    case ACTIONS.TOGGLE_TODO:
      const newTodos = Object.keys(state.todos).map((key) => {
        if (key === action.payload) {
          return { ...state.todos[key], complete: true } // create a new todo item
        }
        else {
          return state.todos[key]; // keep the existing item
        }
      });
      return {...state, todos: newTodos};
于 2020-08-30T08:56:06.830 回答