首页 > 解决方案 > 如何手动强制父组件在子组件中发生的操作时重新渲染?

问题描述

我正在制作一个 react-redux 应用程序,允许用户提交和审查不同的辣酱。

在我的个人资料页面上,我正在呈现两个列表。用户提交的调味汁之一,以及用户评论过的调味汁之一。我的后端有一个级联删除,当它被删除时,它会删除所有对酱汁的评论。目前,如果用户删除酱汁,个人资料页面上的“酱汁已审核”列表不会更新以删除已删除的酱汁,尽管酱汁已从“酱汁提交”列表中正确删除。单击时,评论列表中的酱汁是死链接,因为该酱汁已被删除。如果您手动刷新页面,死链接就会消失,一切正常。我想知道如何手动触发我的配置文件组件的重新渲染

我的想法是使用我的 Profile 组件中定义的虚拟本地状态变量,如下所示:

const [update, setUpdate] = useState(false)

然后,我会将这些变量作为道具传递给我的删除按钮组件,如下所示:

<Profile>
usersauces.map => 
     <div>
         list component stuff
        <Delete update={update} sauce={sauce}  setUpdate={setUpdate}>

然后在我的删除组件中,我有一个句柄删除功能:

const DeleteSauceButton = ({sauce, update, setUpdate}) => {

const handleDelete = async (e) => {
        e.preventDefault()
        await dispatch(thunk_goDeleteSauce(sauce?.id))
        await setUpdate(!update)
        console.log("updated", update)
        history.push(`/users/${userId}`)
    }

我的理解是,删除后子组件中的这种状态变化应该会导致 Profile 父组件的重新渲染,但这并没有发生。当我在设置后 console.log(update) 时,更新仍然是“假”,而不是像我期望的那样“真”。我在这里想念什么?

在我的个人资料组件中,我使用 useSelector 订阅我的状态,如下所示:

const sauceSlice = useSelector(state => state.sauces)
const reviewsSlice = useSelector(state => state.reviews)

const sauces = Object.values(sauceSlice)
const reviews = Object.values(reviewsSlice)

我映射以生成我的列表的列表被过滤如下:

const userReviews = reviews?.filter( review => review?.user_id === userId)
    const userSauces = sauces?.filter( sauce => sauce?.user_id === userId)

我更新的删除酱减速器案例是:

case DELETE_SAUCE: {
        let newState = { ...state }

        delete newState[action.sauce.id]

        return { ...newState }
    }

而review reducer 类似:

const initialState = {}

const reviewReducer = (state = initialState, action) => {
   

     switch (action.type) {
            case LOAD_REVIEWS: {
                return { ...state, ...action.reviews }
            }
            case DELETE_REVIEW: {
                let newState = { ...state }
    
                delete newState[action.reviewId]
    
                return { ...newState }
            }
            case UPDATE_REVIEW: {
                if (!action.review) { return { ...state } }
    
                return {
                    ...state,
                    [action.review.id]: action.review
                }
            }
            default:
                return state
        }
    }

我将 goDeleteSauce thunk 更新为:

export const thunk_goDeleteSauce = (sauce) => async (dispatch) => {
    const res = await fetch(`/api/sauces/${sauce.id}`, {
        method: 'DELETE',
    })

    if (res.ok) {
        sauce.reviews.forEach((review) => dispatch(deleteReview(review.id)))
        dispatch(deleteSauce(sauce))
    }
}

审核操作如下所示:

    export const deleteReview = (reviewId) => ({
    type: DELETE_REVIEW,
    reviewId
})

标签: reactjsreact-reduxreact-hooksuse-state

解决方案


您不应该将 await 与 useState 一起使用:

const handleDelete = async (e) => {
        e.preventDefault()
        await dispatch(thunk_goDeleteSauce(sauce?.id))
        setUpdate(value=>!value)
    }

推荐阅读