我已经用Reaction设置了一个新项目Redux(使用工具包).我有一个按钮,如果用户没有足够的特定资源,就需要禁用它.我已经确认状态正在被正确更新,减速器正在适当地申请状态,但当该资源低于所提供的价格时,我无法获得禁用按钮.

我try 过使用useState钩子从redux复制状态,但在candable()中设置状态仍然不能禁用该按钮.我有点困惑,感觉我只是错过了一些关于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;

推荐答案

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

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;

Reactjs相关问答推荐

NextJs Form不允许我输入任何输入,

For循环中的元素在Reaction中丢失挂钩

如何在Reac.js中通过子组件和props 调用父组件函数?

如何将图像(在代码中称为自己)定位在蓝色圈内的点上?我正在使用material UI和Reaction

如何在单击行中的图标时避免选中ionic 复选框?

NextJS如何正确保存添加到购物车中的产品会话

捕获表单数据时的Reactjs问题

有没有可能在next.js和ssr中使用tsps?

生产部署:控制台中 Firebase 无效 api 密钥错误

React-router动态路径

Mui Datepicker 设置了错误的日期

使用jest如何覆盖对象的模拟?我正在使用`jest.mock()`来模拟对象,并希望 for each 测试用例覆盖模拟.

在添加了useplacesautocomplete后,在构建React/Next.js项目时,NPM抛出类型期望的错误

如何在 React Native 中更新跨屏幕呈现的上下文状态变量?

谁能根据经验提供有关 useEffect 挂钩的更多信息

为什么我在此代码段中看不到 useEffect for count = 1?

在视图列表上react 本机无限循环的反弹动画?

Lodash 在命名导入中导入整个包

多次响应获取发送请求

为什么 state redux-toolkit 是代理?