React视频应用点赞后页面消失报错,刷新点赞数增加问题求助
React视频应用点赞崩溃问题分析与解决
我正在开发一个基于JSON Server的视频应用,其他功能正常,但点击点赞/取消点赞按钮时页面崩溃,抛出Objects are not valid as react child错误,刷新页面后点赞数能正常更新。以下是问题根源和修复方案:
相关代码片段
状态切片代码
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit" import { getVideo, updateReaction } from "./videoApi" const initialState = { video: {}, loading: false, isError: false, error: '' } export const fetchVideo = createAsyncThunk('vidoes/fetchVideo', async (id) => { const videos = await getVideo(id); return videos; }); export const fetchReact = createAsyncThunk('video/reaction', async ({ id, reaction }) => { const videoReaction = await updateReaction({ id, reaction }) return videoReaction; }) const videoSlice = createSlice({ name: 'video', initialState, extraReducers: (builder) => { builder.addCase(fetchVideo.pending, (state) => { state.loading = true; state.isError = false; }) builder.addCase(fetchVideo.fulfilled, (state, action) => { state.loading = false; state.video= action.payload; }) builder.addCase(fetchVideo.rejected, (state, action) => { state.loading = false; state.isError = true; state.error = action.error?.message; state.video = []; }) builder.addCase(fetchReact.pending, (state) => { return state; }) builder.addCase(fetchReact.fulfilled, (state, action) => { state.video.likes = action.payload; state.video.unlikes = action.payload; }) builder.addCase(fetchReact.rejected, (state) => { return state; }) } }); export default videoSlice.reducer;
Video API代码
import axios from '../../utils/axios' export const getVideo = async (id) => { const response = await axios.get(`/videos/${id}`) return response.data; } export const updateReaction = async ({ id, reaction }) => { console.log(id) const { data } = await axios.get(`/videos/${id}`) if (data) { let updatedReaction = reaction === 'like' ? { likes: data.likes + 1, } : { unlikes: data.unlikes + 1, }; const response = await axios.patch(`/videos/${id}`, updatedReaction); return response.data; } }
点赞组件代码
import React from 'react'; import { useDispatch } from 'react-redux'; import LikeImg from '../../assets/like.svg'; import UnLikeImg from '../../assets/unlike.svg' import { fetchReact } from '../../features/video/video_slice'; const LIke = ({ likes, unlikes, id }) => { console.log(id) const dispatch = useDispatch(); const reactionHandler = ({ id, reaction }) => { dispatch(fetchReact({ id, reaction })) } return ( <div className="flex gap-10 w-48"> <div className="flex gap-1"> <div className="shrink-0 cursor-pointer" onClick={() => reactionHandler({ id, reaction: 'like' })} > <img className="w-5 block" src={LikeImg} alt="Like" /> </div> <div className="text-sm leading-[1.7142857] text-slate-600"> {likes >= 1000 ? `${ likes }K` : likes} </div> </div> <div className="flex gap-1"> <div onClick={() => reactionHandler({ id, reaction: 'unlike' })} className="shrink-0 cursor-pointer" > <img className="w-5 block" src={UnLikeImg} alt="Unlike" /> </div> <div className="text-sm leading-[1.7142857] text-slate-600"> {unlikes >= 1000 ? `${ unlikes }K` : unlikes} </div> </div> </div> ); }; export default LIke;
问题根源
1. Redux状态更新逻辑错误
在fetchReact.fulfilled的reducer中,action.payload是API返回的完整视频对象(包含所有字段的JSON数据),但代码错误地将整个对象赋值给了likes和unlikes:
state.video.likes = action.payload; state.video.unlikes = action.payload;
这导致likes和unlikes从数字变成了对象。
2. 组件渲染时尝试渲染对象
在点赞组件中,代码直接渲染likes和unlikes的值:
{likes >= 1000 ? `${ likes }K` : likes}
当likes是对象时,React无法渲染对象类型的子元素,直接抛出Objects are not valid as react child错误,导致页面崩溃。
额外问题
- 无论点赞还是取消点赞,都会同时覆盖
likes和unlikes,导致非目标计数被错误更新 - 视频根页面存在重复的渲染判断,会导致正确内容被错误覆盖
修复方案
1. 修正Redux状态更新逻辑
直接用API返回的完整视频对象替换state中的video,保证所有字段类型正确:
builder.addCase(fetchReact.fulfilled, (state, action) => { state.video = action.payload; })
或者只更新需要的字段(更高效,但需要确保字段对应):
builder.addCase(fetchReact.fulfilled, (state, action) => { state.video.likes = action.payload.likes; state.video.unlikes = action.payload.unlikes; })
2. 修复视频根页面的渲染逻辑
删除重复的错误判断,保留正确的内容渲染分支:
// 删掉这段重复且错误的判断 // if (!loading && !isError && video?.id) { // content = <div className="col-span-12"><srong>{error}</srong></div> // }
3. 可选:优化错误处理
在fetchReact.rejected中添加错误状态更新,方便后续处理错误提示:
builder.addCase(fetchReact.rejected, (state, action) => { state.isError = true; state.error = action.error?.message; })
验证效果
修改完成后,点击点赞/取消点赞按钮时,likes和unlikes会保持数字类型,组件能正常渲染数值,页面不再崩溃,同时点赞数会实时更新,无需刷新页面。
内容的提问来源于stack exchange,提问作者mohammad biplob
相关产品推荐
相关产品推荐

