在 react redux 中设置状态时,我可以获得当前对象的索引吗?
Can I get the index of an object am currently at when setting state in react redux?
我正在使用 React redux 开发一个待办事项应用程序,它的初始状态是一个对象 initialState
并且有一个数组 task
,它是一个空数组。设置 task
的值时,我似乎无法找到一种方法来获取对象的 当前索引 以将其分配给 id
。
我尝试过使用 indexOf()
和 findIndex()
但没有找到处理它的最佳方法。
我希望 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
}
}
您可以使用 state.tasks.length
,但是当您有 2 个任务时会中断,删除第一个任务然后添加一个任务(参见示例,您将以 id 为 1 的 2 个任务结束)。
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>
不建议使用索引,除非你绝对have to并且当你重新订购或从列表中删除项目时永远不要这样做。
我建议制作一个生成 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>
我正在使用 React redux 开发一个待办事项应用程序,它的初始状态是一个对象 initialState
并且有一个数组 task
,它是一个空数组。设置 task
的值时,我似乎无法找到一种方法来获取对象的 当前索引 以将其分配给 id
。
我尝试过使用 indexOf()
和 findIndex()
但没有找到处理它的最佳方法。
我希望 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
}
}
您可以使用 state.tasks.length
,但是当您有 2 个任务时会中断,删除第一个任务然后添加一个任务(参见示例,您将以 id 为 1 的 2 个任务结束)。
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>
不建议使用索引,除非你绝对have to并且当你重新订购或从列表中删除项目时永远不要这样做。
我建议制作一个生成 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>