React - 仅在特定的点击按钮上设置加载状态

IT技术 reactjs
2021-05-16 23:22:04

这是我当前的代码

class cart extends Component {
    state = { loading: [] };

    addToCart = (e, id) => {
        let loading = this.state.loading.slice();
        loading[e] = true;
        this.setState({
            loading,
        })
    };
    render() {
        const { data } = this.props;

        return (
            <div>
            {data.map(catering => {
                const { menus } = catering;

                return (
                    <Row>
                    {menus.map(menu => (
                        <Col xs={12} md={12} lg={6} key={menu.id} className="m-bottom-15">
                        <Card style={{ height: '165px', border: 0, overflow: 'hidden' }}>


                        <CardActions>
                        <LoadingButton
                        className="button small primary pull-right"
                        loading={thi.state.loading || false}
                        onClick={e => this.addToCart(e, menu.id)}
                        >
                        <MdAdd size={18} color={white} />
                        <span className="font-14 font-400">Add to cart</span>
                        </LoadingButton>

                        </CardActions>
                        </Card>
                        </Col>
                        ))}
                    </Row>

                    );
            }
        }

map功能完成后会有大约20个按钮

我想要实现的是:每次用户单击add to cart按钮时,我都会调用 ajax 来保存购物车并显示特定单击按钮的加载。ajax完成后,将状态恢复正常。

在我当前的代码中,我还没有进行 ajax 调用,我仍然想确保加载按钮在按下时工作。现在它不工作。

我怎样才能做到这一点?

谢谢。

3个回答

您的 addToCart 方法中存在一些错误。您应该使用 id 作为加载索引并将加载数组设置为:

addToCart = (e, id) => {
    let loading = this.state.loading.slice();
    loading[id] = true;
    this.setState({
        loading: loading
    });
};

此外,在您的渲染方法中,将 this.state.loading 更改为 this.state.loading[menu.id]:

<LoadingButton
    className="button small primary pull-right"
    loading={this.state.loading[menu.id] || false}
    onClick={e => this.addToCart(e, menu.id)}
>

ajax 调用完成后,您只需调用 setState 函数,该函数在回调方法中将加载数组值设置为 false。

不是bool在 loading中保持而是array菜单 ids 中保持,每当点击 Add 按钮时,将该项目的 id 推送到 loading 中array生成卡片时检查加载是否arrayid,如果有则显示加载,否则显示卡片。

像这样写:

class cart extends Component {

    state = { loading:  []};

    addToCart = (e, id) => {
        let loading = this.state.loading.slice();
        loading.push(id);
        this.setState({
            loading
        })
    };

    render() {
        const { data } = this.props;

        return (
            <div>
            {data.map((catering,i) => {
                const { menus } = catering;
                return (
                    <Row>
                        {menus.map(menu => {
                            return this.state.loading.indexOf(menu.id) >= 0 ?
                                <Col xs={12} md={12} lg={6} key={menu.id} className="m-bottom-15">
                                    <Card style={{ height: '165px', border: 0, overflow: 'hidden' }}>
                                        <CardActions>
                                            <LoadingButton
                                                className="button small primary pull-right"
                                                loading={thi.state.loading || false}
                                                onClick={e => this.addToCart(e, menu.id)}
                                            >
                                                <MdAdd size={18} color={white} />
                                                <span className="font-14 font-400">Add to cart</span>
                                            </LoadingButton>
                                        </CardActions>
                                    </Card>
                                </Col>
                            :
                            /*Loading icon*/
                        })}
                    </Row>
                )
            })}
        )
    }
}

对于钩子们来说,这就是我所做的

const [isLoading, setIsLoading] = useState([]);
<button
        type="button"
        disabled={isLoading[item.username]}
        className="btn btn-success btn-rounded btn-sm my-0"
        onClick={()=>activateOrDeactivate( item.activated,item.username)}
      >      {isLoading[item.username] && <i className="fa fa-circle-o-notch fa-spin"></i>}
      {isLoading[item.username]&& <span> Activating...</span>}
      {!isLoading[item.username]&& <span>Activate</span>}</button>


 const activateOrDeactivate = (valTrueOrFalse,newusername) => {
    let loading = isLoading.slice();
    loading[newusername] = true;
    setIsLoading(loading)
    let config = {
      headers: {
        Authorization: "Bearer " + state.token
      },
    };

    api.post(
      "process-activation",
      {
        activated: !valTrueOrFalse,
        username:newusername
      },
      config
    ).then(
      response => {
        getAllUsers()
        let loading = isLoading.slice();
        loading[newusername] = false;
        setIsLoading(loading)