点击与导航时viewCount始终为0,如何实现递增并传至服务端?
问题分析与解决办法
你遇到的核心问题是React useState的更新是异步的——调用setViewsCount后,当前函数作用域里的viewsCount还是更新前的旧值,所以每次传给服务端的都是初始的0。下面给你两种直接可行的解决思路:
方案一:直接使用计算后的新计数
既然我们能预知更新后的计数,没必要等state异步更新完成再传值,直接计算出新值同时用于更新state和接口参数:
const [viewsCount, setViewsCount] = useState(0); const getClickCount = (id) =>{ console.log("Item Clicked::"+id); // 直接计算更新后的计数 const newCount = viewsCount + 1; setViewsCount(newCount); console.log("Count::"+newCount); const params = { id: id, count: newCount // 用计算好的新值传参 } const fetchData = async () => { try { const res = await axios.put(`${appUrl}/service/updateblogviews`, {params}); if (res.data.success) { } } catch (e) { console.log(e); } } fetchData(); }
如果担心并发点击导致计数不准确(比如短时间内多次点击),可以改用函数式更新的方式确保拿到最新的旧值:
const getClickCount = (id) =>{ console.log("Item Clicked::"+id); let newCount; // 通过函数式更新获取最新的prevCount,计算新值 setViewsCount(prevCount => { newCount = prevCount + 1; return newCount; }); console.log("Count::"+newCount); const params = { id: id, count: newCount } // 接口请求逻辑不变 const fetchData = async () => { try { const res = await axios.put(`${appUrl}/service/updateblogviews`, {params}); if (res.data.success) { } } catch (e) { console.log(e); } } fetchData(); }
方案二:用useEffect监听计数变化
把接口请求逻辑放到useEffect里,监听viewsCount的变化,确保只有当计数更新完成后再调用服务端接口:
const [viewsCount, setViewsCount] = useState(0); // 新增状态存储当前点击的博客ID const [currentBlogId, setCurrentBlogId] = useState(null); // 监听计数和博客ID的变化,更新时触发接口请求 useEffect(() => { if (currentBlogId !== null) { const fetchData = async () => { try { const res = await axios.put(`${appUrl}/service/updateblogviews`, { params: { id: currentBlogId, count: viewsCount // 此时是更新后的最新值 } }); if (res.data.success) { } } catch (e) { console.log(e); } } fetchData(); } }, [viewsCount, currentBlogId]); const getClickCount = (id) =>{ console.log("Item Clicked::"+id); setCurrentBlogId(id); setViewsCount(prevCount => prevCount + 1); }
额外注意点
你代码里外层用了<a>标签包裹可点击的<div>,这会导致:
- 嵌套
<a>标签不符合HTML规范(里面还有一个"Read more"的<a>) - 可能触发两次点击事件,导致计数错误
建议把外层的<a>改成<div>:
<div className='blogArea'> {!results.length && (<div className="noSearchData"><Wave text="Sorry, we couldn't find any results..!" /></div>)} {results.map(({ id, date, photo, heading, blogDetails, reactCode }) => ( <div key={id}> <div className='blogImageSection' onClick={() =>{ getClickCount(id); navigate("blogDetails", { state: { id, date, photo, heading, blogDetails, reactCode } }) }} > {/* 内部内容不变 */} </div> </div> ))} </div>
内容的提问来源于stack exchange,提问作者soccerway
相关产品推荐
相关产品推荐

