You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中修改/删除搜索结果后无法渲染的问题求解

解决搜索状态下待办项删除/编辑后页面不更新的问题

问题描述

我有一个待办项数组和搜索功能,搜索操作会返回过滤后的新数组。但删除或编辑搜索到的项时,页面无法自动渲染这些变化,只有修改搜索关键词后才能正常显示更新。我了解useEffect可以解决该问题,但不清楚回调函数中应写入什么内容,请问该如何解决此问题?

现有代码

ToDoList组件

export const ToDoList = (props: PropsType) => {
    const [searchQuery, setSearchQuery] = useState('')

    const searchedItems = useMemo(() => {
        return props.ToDoData.filter(item => item.text.includes(searchQuery))
    },
        [searchQuery])
    return (
            {props.ToDoData.length ?
                <>
                    <input
                        ...
                        onChange={e => setSearchQuery(e.target.value)}
                    />
                    <ItemsList
                        ...
                        items={
                            searchQuery ?
                                searchedItems :
                                props.ToDoData
                        }
                    />
                </> :
                ...
            }
    )
}

ItemsList组件

export const ItemsList = (props: PropsType) => {
    const [editedText, setEditedText] = useState('')

    const onDeleteItem = (id: number) => {
        props.dispatch(deleteItem(id))
    },
        onEditItemMode = (id: number, text: string) => {
            props.dispatch(setEditMode(true, id))
            setEditedText(text)
        },
        onEditText = (id: number) => {
            props.dispatch(setEditedTextInItem(id, editedText))
            props.dispatch(setEditMode(false, id))
            setEditedText('')
        },
        onToggleCompletedStatus = (id: number, status: string) => {
            ...
        }

    return (
            {props.items.length ?
                props.items.map((object) => (
                    <div
                        className="Item"
                        key={object.id}
                    >
                        {props.inEditMode.some((id: number) => id === object.id) ?
                            <>
                                <input
                                    value={editedText}
                                    onChange={e => { setEditedText(e.currentTarget.value) }}
                                />
                                <button onClick={() => onEditText(object.id)}>
                                    Change text
                                </button>
                            </> :
                            <>
                                <div className="Item__textBlock">
                                    <input
                                        type='checkbox'
                                        onClick={() => { onToggleCompletedStatus(object.id, object.status)}}
                                    />
                                    <span className={
                                        object.status === 'completed' ?
                                            'completed' :
                                            'in process'
                                    }>
                                        {object.text}
                                    </span>
                                </div>
                                <div className="Item__buttonBlock">
                                    <button
                                        className="Item__button"
                                        disabled={props.inEditMode.length !== 0}
                                        onClick={() => onEditItemMode(object.id, object.text)}
                                    >
                                        <img src={editImg} />
                                    </button>
                                    <button
                                        className="Item__button"
                                        onClick={() => { onDeleteItem(object.id) }}
                                    >
                                        <img src={removeImg} />
                                    </button>
                                </div>
                            </>
                        }
                    </div>
                )) :
                ...
            }
    )
}

问题原因

问题出在useMemo的依赖数组配置上:你当前仅将searchQuery作为searchedItems的依赖项,当删除、编辑操作修改了props.ToDoData时,useMemo不会重新执行过滤计算,导致searchedItems始终是旧的过滤结果,ItemsList组件拿到的还是旧数据,因此不会触发页面更新。

解决方案

不需要使用useEffect,只需修正useMemo的依赖数组,把props.ToDoData也加入其中。这样每当原待办数据变化,或者搜索关键词变化时,都会重新计算过滤后的结果,页面就能自动更新。

修改后的ToDoList组件代码

export const ToDoList = (props: PropsType) => {
    const [searchQuery, setSearchQuery] = useState('')

    const searchedItems = useMemo(() => {
        return props.ToDoData.filter(item => item.text.includes(searchQuery))
    },
        // 新增props.ToDoData作为依赖项
        [searchQuery, props.ToDoData])
    return (
            {props.ToDoData.length ?
                <>
                    <input
                        ...
                        onChange={e => setSearchQuery(e.target.value)}
                    />
                    <ItemsList
                        ...
                        items={
                            searchQuery ?
                                searchedItems :
                                props.ToDoData
                        }
                    />
                </> :
                ...
            }
    )
}

额外注意事项

确保你的状态更新是不可变的:删除或编辑待办项时,必须返回新的数组,而不是直接修改原数组。比如:

  • 删除操作的reducer示例:
case 'deleteItem':
  return {
    ...state,
    ToDoData: state.ToDoData.filter(item => item.id !== action.payload)
  }
  • 编辑文本的reducer示例:
case 'setEditedTextInItem':
  return {
    ...state,
    ToDoData: state.ToDoData.map(item => 
      item.id === action.payload.id 
        ? {...item, text: action.payload.text} 
        : item
    )
  }

内容的提问来源于stack exchange,提问作者Aaaaaaaaa Aaaaaaaaa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 13:24:47