You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中useEffect首次触发后setState无法再次生效的问题

React函数组件中调用合约后状态不更新的解决方法

问题根源

  1. 闭包陷阱:callSmartContract里直接访问的approvalsList是组件初始渲染时被闭包捕获的旧状态,合约调用成功后过滤的是旧数组,导致状态更新无法反映最新数据。
  2. useEffect无依赖数组:你的useEffect没设置依赖项,会在组件每次渲染时都触发API请求,不仅浪费资源,还可能干扰状态更新逻辑。
  3. 冗余状态管理:noApprovals可以直接通过approvalsList.length判断,不需要单独维护状态,减少出错概率。

修复方案

1. 用函数式更新修改状态

React的setState支持传入函数,函数会接收当前最新的状态值,彻底避开闭包问题:

setApprovalsList(prevList => prevList.filter(e => e !== address));

2. 给useEffect添加依赖数组

把publicAddress作为依赖项,确保只有当地址变化时才重新请求数据,避免无限循环:

useEffect(()=>{
    axios.get("http://localhost:3001/get-user",{
        params:{ address: publicAddress }
    }).then((response) => {
        const jsonArray = JSON.parse(response.data.approved_users);
        setApprovalsList(jsonArray);
    })
}, [publicAddress]); // 添加依赖数组

3. 移除冗余的noApprovals状态

直接在渲染时判断approvalsList.length === 0,不用单独维护状态:

{approvalsList.length === 0 &&
    <center style={{paddingTop:"150px"}}>
        <h2>You have no users to approve</h2>
    </center>
}

完整修复后的代码

function Approvals(){
    const [approvalsList, setApprovalsList] = useState([]);

    const publicAddress = localStorage.getItem("public_address");
    const web3JSON = localStorage.getItem("web3");
    const web3 = JSON.parse(web3JSON);

    useEffect(()=>{
        axios.get("http://localhost:3001/get-user",{
            params:{ address: publicAddress }
        }).then((response) => {
            const jsonArray = JSON.parse(response.data.approved_users);
            setApprovalsList(jsonArray);
        })
    }, [publicAddress])

    const callSmartContract = async (address) => {
        const currentProvider = detectCurrentProvider();
        if (currentProvider) {
            await currentProvider.request({method: 'eth_requestAccounts'});
            const web3 = new Web3(currentProvider);
            const userAccount = await web3.eth.getAccounts();
            const account = userAccount[0].toString();
            const UserContract = new web3.eth.Contract(User.value,"0xEeA1fcb8280d3723d0930C5fB8281D93929D4e2f",{
                from: account
            });
            await UserContract.methods.giveApproval(account, address).send();
            alert("Success");
            // 使用函数式更新获取最新状态
            setApprovalsList(prevList => prevList.filter(e => e !== address));
        }
    }

    return(
        <div>
            <center style={{paddingTop:"150px"}}>
                <h2>Please select which doctor you would like to approve.</h2>
            </center>
            <center style={{paddingTop:"350px"}}>
                <Box style={{borderRadius: '16px', backgroundColor: '#6ea6be',width:"700px"}}>
                    <List sx={{width: '700px', maxWidth: '1000px'}}>
                        {approvalsList.map((item)=>{
                            return  <ListItemButton component="a" onClick={()=>callSmartContract(item)}>
                                <ListItemText primary={item} secondary="Accept Approval Request" />
                            </ListItemButton>;
                        })}
                    </List>
                </Box>
            </center>
            {approvalsList.length === 0 &&
                <center style={{paddingTop:"150px"}}>
                    <h2>You have no users to approve</h2>
                </center>
            }
        </div>
    )
}

内容的提问来源于stack exchange,提问作者Khandkar Islam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 21:40:28