1

我正在使用 react redux 开发一个待办事项应用程序,它的初始状态是一个对象initialState,并且有一个数组 task,它是一个空数组。在设置 的值时task,我似乎无法找到一种方法来获取对象的当前索引以将其分配给id。我尝试过使用indexOf()and thefindIndex()但还没有找到最好的方法来处理它。我希望 id 等于其对象的索引。(如果对象在任务数组中的索引 0 处,则该 id 等于 0)并且在数组更改或具有多个对象时也可以工作。感谢您的帮助,谢谢

这是我的初始状态

export const initialState = {
    task: []
}

这是我的减速机

const manageTodoReducer = (state, action) => {
    switch(action.type) {
        case "ADD_TODO":
            return (
                {
                    ...state,
                    task: [
                        ...state.task, 
                        {
                            name: "This is the name", 
                            id: state.task.findIndex(x => x.name === state.task.name), 
                            complete: false
                    }]
                }
            )

            default:
                return state
            }
        }
4

1 回答 1

0

您可以使用state.tasks.length,但是当您有 2 个任务时会中断,删除第一个然后添加一个任务(参见示例,您将以 2 个 id 为 1 的任务结束)。

const { Provider, useDispatch, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;

const initialState = {
  tasks: [{ id: 0 }, { id: 1 }],
};
//action types
const ADD_TASK = 'ADD_TASK';
const REMOVE_TASK = 'REMOVE_TASK';
//action creators
const addTask = () => ({
  type: ADD_TASK,
});
const removeTask = (id) => ({
  type: REMOVE_TASK,
  payload: id,
});
const reducer = (state, { type, payload }) => {
  if (type === ADD_TASK) {
    return {
      ...state,
      tasks: state.tasks.concat({ id: state.tasks.length }),
    };
  }
  if (type === REMOVE_TASK) {
    return {
      ...state,
      tasks: state.tasks.filter(({ id }) => id !== payload),
    };
  }
  return state;
};
//selectors
const selectTasks = (state) => state.tasks;
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(
      () => (next) => (action) => next(action)
    )
  )
);
const App = () => {
  const tasks = useSelector(selectTasks);
  const dispatch = useDispatch();
  const remove = (id) => dispatch(removeTask(id));
  const add = () => dispatch(addTask());
  return (
    <div>
      <button onClick={add}>Add task</button>
      <ul>
        {tasks.map((task) => (
          <li key={task.id}>
            <pre>{JSON.stringify(task)}</pre>
            <button onClick={() => remove(task.id)}>
              remove
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
};

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>

<div id="root"></div>

不建议使用 index ,除非您在重新订购或从列表中删除项目时绝对必须这样做并且永远不要这样做。

我建议制作一个生成 id 的函数:

//in case you use redux persist and tasks will persist between reloads
const genId = (state) =>
  Math.max(...state.map(({ id }) => id).concat(-1)) + 1;    

//reducer
id: genId(state.tasks),

请参阅下面的工作示例

const { Provider, useDispatch, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;

const initialState = {
  tasks: [{ id: 0 }, { id: 1 }],
};
//action types
const ADD_TASK = 'ADD_TASK';
const REMOVE_TASK = 'REMOVE_TASK';
//action creators
const addTask = () => ({
  type: ADD_TASK,
});
const removeTask = (id) => ({
  type: REMOVE_TASK,
  payload: id,
});
//in case you use redux persist and tasks will persist between reloads
const genId = (state) =>
  Math.max(...state.map(({ id }) => id).concat(-1)) + 1;
const reducer = (state, { type, payload }) => {
  if (type === ADD_TASK) {
    return {
      ...state,
      tasks: state.tasks.concat({
        id: genId(state.tasks),
      }),
    };
  }
  if (type === REMOVE_TASK) {
    return {
      ...state,
      tasks: state.tasks.filter(({ id }) => id !== payload),
    };
  }
  return state;
};
//selectors
const selectTasks = (state) => state.tasks;
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(
      () => (next) => (action) => next(action)
    )
  )
);
const App = () => {
  const tasks = useSelector(selectTasks);
  const dispatch = useDispatch();
  const remove = (id) => dispatch(removeTask(id));
  const add = () => dispatch(addTask());
  return (
    <div>
      <button onClick={add}>Add task</button>
      <ul>
        {tasks.map((task) => (
          <li key={task.id}>
            <pre>{JSON.stringify(task)}</pre>
            <button onClick={() => remove(task.id)}>
              remove
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
};

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>

<div id="root"></div>

于 2021-06-11T13:34:40.377 回答