Reactjs 使用React中的dispatch将数组中的项替换为新值

Reactjs 使用React中的dispatch将数组中的项替换为新值,reactjs,react-hooks,dispatch,use-reducer,Reactjs,React Hooks,Dispatch,Use Reducer,我有一个初始数组,可以从中添加和删除,没有问题 const initialItems = [ { id: Date.now(), text: 'Get milk', }, { id: Date.now(), text: 'Get eggs', }, ] ..但我想知道如何使用分派功能有效地编辑其中一个项目的文本 我的调度如下所示: const editItemHandler = () => {

我有一个初始数组,可以从中添加和删除,没有问题

const initialItems = [
    {
        id: Date.now(),
        text: 'Get milk',
    },
    {
        id: Date.now(),
        text: 'Get eggs',
    },
]
..但我想知道如何使用分派功能有效地编辑其中一个项目的文本

我的调度如下所示:

const editItemHandler = () => {
    dispatch({
        type: 'EDIT_ITEM',
        id: Date.now(),
        text: itemInputRef.current.value,
        index,
    })
}
const itemReducer = (state, action) => {
    switch (action.type) {
        case 'ADD_ITEM': {
            return [
                ...state,
                {
                    id: action.id,
                    text: action.text,
                },
            ]
        }
        case 'EDIT_ITEM': {
            // Attempt 1
            return [...state.splice((item, index) => index, 1, action.text)]
            // Attempt 2
            return [
                ...state.filter((item, index) => index !== action.index),
                {
                    id: action.id,
                    text: action.text,
                },
           ]
        }
        case 'DELETE_ITEM': {
            return [...state.filter((item, index) => index !== action.index)]
        }
        default: {
            return state
        }
    }
}

export default itemReducer
这只是传递输入的值

<input
    autoFocus
    type='text'
    ref={itemInputRef}
    onKeyDown={(e) => {
        if (e.key === 'Escape') {
            setToggle(!toggle)
        }
        if (e.key === 'Enter') {
            // Dispatch
            editItemHandler()
            setToggle(!toggle)
        }
    }}
/>
我已经在“EDIT_ITEM”类型中尝试了两种方法

方法1只是删除该项并添加一个新的值项,尽管它位于数组的底部,但这不是我想要的,因此我必须尝试在之后重新排序

方法2是使用拼接,我认为这是用指定值替换项目的有效方法。但是,它返回的只是带有原始文本的“已编辑”文本(因此甚至未编辑),并删除其他所有内容

我是如何错误地使用此功能的,还是有更好的方法来编辑项目?我显然做错了什么,但不知道是什么。我到处搜索,尝试了各种方法,但都没有结果


理想情况下,我希望该项也保持与以前相同的id,因此如何保持该id将是一个加号。

要更新数组中的项,您有以下几种选择:

case 'EDIT_ITEM': {
    // using map
    return state.map((item, i) => 
                    i === action.index ? { id: action.id, text: action.text } : item
    // using slice
    return [
      ...state.slice(0, action.index),
      { id: action.id, text: action.text },
      ...state.slice(action.index+1)
    ]
这是对
拼接的错误使用

return[…state.splice((项目,索引)=>index,1,action.text)]

因为返回一个包含已删除元素的数组,它不接受函数作为第一个参数,而是接受开始更改数组的索引

正确的拼接方法:

case 'EDIT_ITEM': {
    // using splice
    let newState = [ ...state ]
    newState.splice(action.index, 1, { id: action.id, text: action.text })
    // or you can directly do
    newState[action.index] = { id: action.id, text: action.text }
    // and return the new state
    return newState;

要更新数组中的项,您有几个选择:

case 'EDIT_ITEM': {
    // using map
    return state.map((item, i) => 
                    i === action.index ? { id: action.id, text: action.text } : item
    // using slice
    return [
      ...state.slice(0, action.index),
      { id: action.id, text: action.text },
      ...state.slice(action.index+1)
    ]
这是对
拼接的错误使用

return[…state.splice((项目,索引)=>index,1,action.text)]

因为返回一个包含已删除元素的数组,它不接受函数作为第一个参数,而是接受开始更改数组的索引

正确的拼接方法:

case 'EDIT_ITEM': {
    // using splice
    let newState = [ ...state ]
    newState.splice(action.index, 1, { id: action.id, text: action.text })
    // or you can directly do
    newState[action.index] = { id: action.id, text: action.text }
    // and return the new state
    return newState;

太棒了,谢谢。我明白我是怎么用错了。您发布的前两个方法刚刚返回了带有新条目的重复数组。不过,您编辑的拼接方法和直接针对数组索引的方法都可以很好地工作。但奇怪的是,只有在从
editItemHandler
中删除对index的调用之后。否则,它只更新顶级数组项。我真的不明白为什么会这样
const editItemHandler=(index)//我不知道您是如何管理代码中的索引的,但请确保将适当的索引传递给减速机,我将从我的回答中删除此部分。我的错误是,我忘了在调用函数
editItemHandler(index)
的地方传递它。不过,不管在我这边和那边都很好。太棒了,谢谢。我明白我是怎么用错了。您发布的前两个方法刚刚返回了带有新条目的重复数组。不过,您编辑的拼接方法和直接针对数组索引的方法都可以很好地工作。但奇怪的是,只有在从
editItemHandler
中删除对index的调用之后。否则,它只更新顶级数组项。我真的不明白为什么会这样
const editItemHandler=(index)//我不知道您是如何管理代码中的索引的,但请确保将适当的索引传递给减速机,我将从我的回答中删除此部分。我的错误是,我忘了在调用函数
editItemHandler(index)
的地方传递它。不过,在我这方面,不管有没有,都很好。