【发布时间】:2021-10-01 23:03:13
【问题描述】:
我正在制作一个 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
})
【问题讨论】:
-
您如何订阅其他组件中的评论列表?当您删除酱汁时,应该更新 redux 状态(包括评论),以便其他组件会自动重新渲染最新的更改。
-
在 Profile 组件或 Delete 按钮组件中?
-
在您订阅商店状态的任何组件中。您是否正在删除与
thunk_goDeleteSauce生成的操作中删除的酱汁相关的所有评论?如果没有,那就是删除酱汁时缺少的步骤。 -
这是有道理的,肯定是错过了这一点。我认为这帮助我走上了正确的道路,我重新配置了我的动作创建器、删除酱 thunk 和减速器中的 DELETE_SAUCE 案例,以便能够接受整个酱对象而不是 id。这样我就可以访问诸如 sauce.reviews 之类的评论,并对每个评论发送一个 thunk。不幸的是,我还没有完全到那里,但这绝对有帮助
-
如果没有可重复的示例,我真的无法提出更多建议,但听起来您现在正在考虑所有正确的部分。当您由于某种原因无法控制应用程序的某些部分时,您应该将手动重新渲染视为仅作为黑客/逃生舱口。订阅您的商店并根据其数据的更新进行渲染是正确的继续方式。
标签: reactjs react-redux react-hooks use-state