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

如何重构Hook调用避免无效Hook错误并正确传递状态

问题解决:React Hook调用错误及代码重构

问题还原

报错信息:Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
需求:重构代码,确保将每个assessmentData推入listItems时,能传递对应正确的isGood和isSubGood状态,问题出在listItems.push的代码逻辑里。

错误根源

  1. 闭包陷阱:在useEffect循环里调用setIsGood/setIsSubGood后立即获取状态值,由于闭包特性,拿到的永远是组件初始化时的false,并非刚更新的状态。
  2. 状态滥用:isGood/isSubGood是每个assessmentData的临时计算值,不需要放到组件全局状态中,全局状态应只存储跨渲染周期共享或控制UI显示的值。
  3. 变量追踪失效:listItems是普通变量,React无法追踪其变化,组件重新渲染时会被重置,加上useEffect空依赖仅执行一次,导致渲染内容异常。
  4. 拼写错误:代码中setIsGoog(true)是笔误,应为setIsGood(true)。

重构后的代码

export default function AssessmentsGraphData(props) {
    const [createModal, setCreateModal] = React.useState(false);
    const [error, setError] = React.useState(false);

    const { data: graphData, isUserAllowedEdit, userId, handleUpdateSuccess } = props;

    // 用useMemo缓存处理后的listItems,避免重复计算
    const listItems = React.useMemo(() => {
        if (!graphData) return [];
        
        return graphData.map((assessmentData) => {
            // 实时计算当前assessment对应的isGood和isSubGood
            let isGood = false;
            let isSubGood = false;

            if (assessmentData.assessmentType === 'HERE') {
                isGood = true;
            }
            if (['THAT', 'THIS', 'OTHER'].includes(assessmentData.assessmentType)) {
                isGood = true;
                isSubGood = true;
            }

            return Assessment.individualAssessment(
                assessmentData,
                userId,
                isGood,
                isSubGood,
                isUserAllowedEdit,
                handleUpdateSuccess,
            );
        });
    }, [graphData, userId, isUserAllowedEdit, handleUpdateSuccess]);

    // 计算全局isGood,用于控制底部Card显示
    const isGood = React.useMemo(() => {
        if (!graphData) return false;
        return graphData.some(assessmentData => {
            return assessmentData.assessmentType === 'HERE' || ['THAT', 'THIS', 'OTHER'].includes(assessmentData.assessmentType);
        });
    }, [graphData]);

    return (
        <React.Fragment>
            <Drilldown
                animateHeight
                aria-label="Results"
                data={{
                    panel: {
                        listHeader: 'Member',
                        listItems: listItems
                    }
                }}
            />
            <br />
            {!isGood ? (
                <Card>
                    <Card.Body>
                        <Headline>Create new for selected member</Headline>
                        <br />
                        <br />

                        <Modal open={createModal} onClose={setCreateModal} large>
                            <Modal.Body>
                                <CreatePvnAssessment
                                    isUserAllowedEdit={isUserAllowedEdit}
                                    memberPartyId={graphData.partyId}
                                    memberPartyIdType={graphData.partyIdType}
                                    userId={userId}
                                    handleUpdateSuccess={handleUpdateSuccess}
                                />
                            </Modal.Body>
                        </Modal>
                        <Modal open={error} onClose={setError} small>
                            <Modal.Body>
                                <Headline p={15}>Record failed to update</Headline>
                            </Modal.Body>
                        </Modal>
                        <Grid.Row>
                            <Grid.Column sm="6">
                                <Button onClick={() => setCreateModal(true)}>Create</Button>
                            </Grid.Column>
                        </Grid.Row>
                    </Card.Body>
                </Card>
            ) : null}
        </React.Fragment>
    );
}

重构说明

  • 移除全局的isGood/isSubGood状态,改为处理每个assessmentData时实时计算对应值并直接传递给子组件,规避闭包和状态更新问题。
  • 用useMemo缓存listItems和全局isGood的值,仅在依赖项变化时重新计算,提升性能。
  • 解构props简化代码,修复setIsGoog的拼写错误。
  • 移除冗余的results变量,直接返回JSX,代码逻辑更直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 13:26:01