javascript - react setState() 在第一次点击时不起作用,但在第二、第三次点击时工作正常……点击
问题描述
setState() 在第一次点击时不起作用!状态值仅在第二次、第三次 ....clicks 时更新。我使用适当的上下文和导入来处理状态!
我将快速总结一下我在做什么顶部导航栏有两个按钮,主页和购物车。侧导航栏有三个英雄按钮,点击会呈现相应的英雄商店,其中有 T 恤、袜子和鞋子,带有 + 和 - 按钮来增加或减少数量。
在每次点击时,显示数量的 span 值正确增加,但购物车按钮显示的数量不包括第一次点击。就像当我将 tshirts 值增加到 1 时,购物车按钮不显示任何值,当我将 tshirts 值增加到 2 时,购物车按钮显示 1
cartButton 使用状态 CartValue tshirts,socks,shoes 使用状态 HeroGoods
(现场演示)单击此处查看我在说什么
我不确定我是否允许在此处发布所有组件和外部链接,例如 github。但无论如何,如果你们从下面的代码中看不到我哪里出错了,这里是 github repo 的链接
import React , {useState,useEffect}from 'react';
import Navmenu from './Navmenu'
import SideNav from './SideNav'
import ActionDiv from './ActionDiv'
import ActionHeroStore from './ActionHeroStore'
import ActionCart from './ActionCart'
import '../css/main.css'
export const HeroContext=React.createContext()
const emptyGood={
tshirts:0,
shoes:0,
socks:0,
}
const emptyCart={
batman:{
tshirts:0,
shoes:0,
socks:0,
},
superman:{
tshirts:0,
shoes:0,
socks:0,
},
greenlantern:{
tshirts:0,
shoes:0,
socks:0,
},
}
function empty()
{
return null
}
function App() {
const [hero,setHero]=useState(null)
const [cartValue,setCartValue]=useState(emptyCart)
const [batmanGoods,setBatmanGoods]=useState(emptyGood)
const [supermanGoods,setSupermanGoods]=useState(emptyGood)
const [greenLanternGoods,setGreenLanternGoods]=useState(emptyGood)
const [showCart,setShowCart]=useState(false)
function handleUpdateGoods(hero,obj){
hero=='batman'?
setBatmanGoods(prevState=>{
return {...prevState,...obj}
}):
hero=='superman'?
setSupermanGoods(prevState=>{
return {...prevState,...obj}
}):
hero=='greenlantern'?
setGreenLanternGoods(prevState=>{
return {...prevState,...obj}
}):
empty()
}
function handleHeroSelect(name){
setHero(prevState=>prevState=name)
}
function handleCartValue(value)
{
setCartValue(value)
}
function handleShowCart(status)
{
setShowCart(status)
}
function giveHeroGoods(hero,element)
{
return (
hero=='batman'?batmanGoods[element]:
hero=='superman'?supermanGoods[element]:
hero=='greenlantern'?greenLanternGoods[element]:empty()
)
}
function handleUpdateCart(name){
name=='batman'?
setCartValue(prevState=>{
return {...prevState,batman:{...batmanGoods}}
}):
name=='superman'?
setCartValue(prevState=>{
return {...prevState,superman:{...supermanGoods}}
}):
name=='greenlantern'?
setCartValue(prevState=>{
return {...prevState,greenlantern:{...greenLanternGoods}}
}):
empty()
}
const heroContextValue={
handleHeroSelect,
handleCartValue,
handleUpdateGoods,
giveHeroGoods,
handleUpdateCart,
handleShowCart
}
return (
<>
<HeroContext.Provider value={heroContextValue}>
<Navmenu cartValue={cartValue}/>
<div className="mainContent">
<SideNav cartValue={cartValue}/>
{hero==null && !showCart &&<ActionDiv/>}
{hero!==null && !showCart && <ActionHeroStore hero={hero}/>}
{showCart && <ActionCart cartValue={cartValue}/>}
</div>
</HeroContext.Provider>
</>
)
}
export default App;
import React ,{useContext} from 'react'
import {HeroContext} from './App'
export default function Navmenu(props) {
const {cartValue}=props
const {handleHeroSelect,handleShowCart}=useContext(HeroContext)
function giveGoodsSum(obj)
{
return obj.tshirts+obj.socks+obj.shoes
}
function giveCartValue(cartValue){
let sum=0
for(let key in cartValue)
{
sum=sum+giveGoodsSum(cartValue[key])
}
return(
sum!==0?sum:null
)
}
return (
<div
className="navMenu"
>
<button
className="homeButton"
onClick={()=>{
handleHeroSelect(null)
handleShowCart(false)
}}
>
Home
</button>
<button
className="cartButton"
onClick={()=>{
handleHeroSelect(null)
handleShowCart(true)
}}
>
cart
<span
>
{giveCartValue(cartValue)}
</span>
</button>
</div>
)
}
import React ,{useContext} from 'react'
import {HeroContext} from './App'
export default function SideNav() {
const {handleHeroSelect}=useContext(HeroContext)
return (
<div className="sideNav">
<div
className="batman"
onClick={()=>handleHeroSelect('batman')}
/>
<div
className="superman"
onClick={()=>handleHeroSelect('superman')}
/>
<div
className="greenlantern"
onClick={()=>handleHeroSelect('greenlantern')}
/>
</div>
)
}
import React from 'react'
import ActionHeroStoreGoods from './ActionHeroStoreGoods'
export default function ActionHeroStore(props) {
const {hero}=props
return (
<div className={`actionHeroStore ${hero}div`}>
<h3>{hero}</h3>
<div className="actionHeroStore_goods">
<ActionHeroStoreGoods hero={hero}/>
</div>
</div>
)
}
import React, { Fragment,useContext } from 'react'
import {HeroContext} from './App'
export default function ActionHeroStoreGoods({hero}) {
const {giveHeroGoods,
handleUpdateGoods,
handleUpdateCart
}=useContext(HeroContext)
const goods=['tshirts','shoes','socks'];
const goodsElement=goods.map((element,index) => {
return <Fragment key={index}>
<div className="soloGood">
<span>{element}</span>
<button
onClick={
()=>decrement(hero,element)
}>-</button >
<span>{giveHeroGoods(hero,element)}</span>
<button onClick={
()=>{
increment(hero,element)
handleUpdateCart(hero)
}
}>+</button>
</div>
</Fragment>
})
function increment(hero,element){
let updateObj={};
updateObj[element]=giveHeroGoods(hero,element)+1
handleUpdateGoods(hero,updateObj)
}
function decrement(hero,element){
if(giveHeroGoods(hero,element)>0)
{
let updateObj={};
updateObj[element]=giveHeroGoods(hero,element)-1
handleUpdateGoods(hero,updateObj)
}
}
return (
<>
{goodsElement}
</>
)
}
解决方案
问题不在 setState 中。代码中的问题。在更改 *Goods 状态之前调用 handleUpdateCart() 函数。所以它适用于旧数据。如果您将在“App.js”文件中添加以下片段:
...
...
function giveHeroGoods(hero,element)
{
return (
hero=='batman'?batmanGoods[element]:
hero=='superman'?supermanGoods[element]:
hero=='greenlantern'?greenLanternGoods[element]:empty()
)
}
// FROM HERE
React.useEffect(() => {
handleUpdateCart('batman');
}, [
batmanGoods
]);
React.useEffect(() => {
handleUpdateCart('superman');
}, [
supermanGoods
]);
React.useEffect(() => {
handleUpdateCart('greenlantern');
}, [
greenLanternGoods
]);
// TILL HERE
function handleUpdateCart(name){
...
...
推荐阅读
- python-3.x - 如何包含循环或乘以循环直到满足精度?
- python - Python - TypeError:“NoneType”对象不可下标
- apache-spark - 如何加载火花模型
- sql - 如何查找具有前导零的记录及其对应部分(重复)记录并将其组合在一起,该记录已在数据库中删除了前导零
- objective-c - NSDictionary 获取值作为字符串不会抱怨但 lenngth 或 isEqualToString 崩溃
- php - 如何将 Laravel 数据透视量与表格列进行比较
- swift - 当我使用 SceneKit 在虚拟房间内的 SCNBox 周围移动 SCNCamera 时,房间纹理未完全渲染
- http - 如何最小化 HTTP POST 请求?
- node.js - Windows 的电子构建显示 sqlite3 错误。但是 Ubuntu Works 的相同版本
- amazon-web-services - AWS sagemaker 上的多用户公共 jupyter 笔记本