在redux状态更改时更新React按钮禁用状态

1zmg4dgp  于 2022-11-12  发布在  React
关注(0)|答案(1)|浏览(141)

我用React Redux(使用工具包)建立了一个新项目。如果用户没有足够的特定资源,我有一个按钮需要禁用。我已经确认状态被正确更新,reducer正确应用到状态,但是当资源福尔斯提供的价格时,我无法禁用按钮。
我尝试过使用useState钩子从redux复制状态,但是在canAfford()中设置状态仍然不能禁用按钮。我有点不知所措,感觉我只是缺少了一些关于redux状态和渲染的东西。
下面是我正在使用的按钮组件:

function BuyBtn({ technology, label, resourceType, price, requirements = []}: IBuyBtn) {
    const units = useSelector((state: any) => state.units);
    const tech = useSelector((state: any) => state.tech);
    const resources = useSelector((state: any) => state.resources);
    const dispatch = useDispatch();

    let disabled = false;
    let unlocked = true;

    useEffect(() => {
        disabled = !canAfford()
    }, [resources])

    const canAfford = (): boolean => {
        console.log('Units:', units);
        console.log("Checking affordability");
        if (resourceType.length != price.length) {
            throw `BuyBtn Error: price length is ${price.length} but resource length is ${resourceType.length}.`;
        }

        resourceType.forEach((res, i) => {
            const resPrice = price[i];
            if (resources[res] < resPrice) {
                return false;
            }
        });

        return true;
    };

    const meetsRequirements = (): boolean => {
        if (requirements.length === 0) {
            return true;
        }

        requirements.forEach((req) => {
            if (!tech[req]) {
                return false;
            }
        });

        return true;
    };

    const buyThing = () => {
        if (canAfford() && meetsRequirements()) {
            resourceType.forEach((res, i) => {
                const resPrice = price[i];
                dispatch(SubtractResource(res, resPrice));
            });

            dispatch(UnlockTech(technology, true))
        }
    };

    if (meetsRequirements() && canAfford()) {
        return (
            <button onClick={buyThing} disabled={disabled}>{label}</button>
        );
    } else {
        return null;
    }

}

export default BuyBtn;
r8uurelv

r8uurelv1#

不使用disabled作为变量,而是将其设置为State,这将触发重新渲染:

function BuyBtn({ technology, label, resourceType, price, requirements = []}: IBuyBtn) {
    const units = useSelector((state: any) => state.units);
    const tech = useSelector((state: any) => state.tech);
    const resources = useSelector((state: any) => state.resources);
    const dispatch = useDispatch();

    const [disabled, setDisabled] = React.useState(false);
    let unlocked = true;

    const canAfford = (): boolean => {
        console.log('Units:', units);
        console.log("Checking affordability");
        if (resourceType.length != price.length) {
            throw `BuyBtn Error: price length is ${price.length} but resource length is ${resourceType.length}.`;
        }

        let isAffordable = true
        resourceType.forEach((res, i) => {
            const resPrice = price[i];
            if (resources[res] < resPrice) {
                isAffordable = false;
            }
        });

        return isAffordable;
    };

    useEffect(async() => {
        const value = await canAfford();
        setDisabled(!value);
    }, [resources])

    const meetsRequirements = (): boolean => {
        if (requirements.length === 0) {
            return true;
        }

        let isMeetingRequirements = true;
        requirements.forEach((req) => {
            if (!tech[req]) {
                isMeetingRequirements = false;
            }
        });

        return isMeetingRequirements;
    };

    const buyThing = () => {
        if (canAfford() && meetsRequirements()) {
            resourceType.forEach((res, i) => {
                const resPrice = price[i];
                dispatch(SubtractResource(res, resPrice));
            });

            dispatch(UnlockTech(technology, true))
        }
    };

    if (meetsRequirements() && canAfford()) {
        return (
            <button onClick={buyThing} disabled={disabled}>{label}</button>
        );
    } else {
        return null;
    }

}

export default BuyBtn;

相关问题