简体   繁体   English

如何更改动作创建器 function 中组件的内部 state 属性

[英]How to change the internal state property of a component in an action creator function

I am working on a React application and I am using Redux to store the state.我正在开发一个 React 应用程序,我正在使用 Redux 来存储 state。 I have the following code:我有以下代码:

category-arrows.component.jsx:类别箭头.component.jsx:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { increaseCategoryRank, decreaseCategoryRank, fetchCategoryRanks } from '../../redux/menu/menu.actions';
import './category-arrows.styles.scss';

class CategoryArrows extends Component {

    state = {
        isSending: false
    }

    render() {

        const { category } = this.props;
        const categoryClicked = true;

        return (
            <div className="arrows-container">
                <div className="up-arrow" onClick={
                    () => {
                        if(this.state.isSending === false) {
                            this.props.increaseCategoryRank(category, categoryClicked)
                        }
                        this.props.fetchCategoryRanks(this.props.menu);
                }}></div>
                <div className="category-rank">
                    <p>{category.rank}</p>
                </div>
                <div className="down-arrow" onClick={
                    () => {
                        if(this.state.isSending === false) {
                            this.props.decreaseCategoryRank(category, categoryClicked)
                        }
                        this.props.fetchCategoryRanks(this.props.menu);
                }}></div>
            </div>
        )
    }
}

const mapStateToProps = state => ({
    menu: state.menu
})

export default connect(mapStateToProps, { increaseCategoryRank, decreaseCategoryRank, fetchCategoryRanks } )(CategoryArrows);

menu.actions.js: menu.actions.js:

import { apiUrl, apiConfig } from '../../util/api';
import { INCREASE_CATEGORY_RANK, DECREASE_CATEGORY_RANK, FETCH_CATEGORY_RANKS } from './menu.types';

export const decreaseCategoryRank = (category, categoryClicked) => dispatch => {
    dispatch({ type: DECREASE_CATEGORY_RANK, category, categoryClicked })
}

export const increaseCategoryRank = (category, categoryClicked)  => dispatch => {
    dispatch({ type: INCREASE_CATEGORY_RANK, category, categoryClicked })
}

export const fetchCategoryRanks = menu => async dispatch => {
    console.log("Printing menu (fetch category ranks)");
    console.log(menu);

    var sentRequests = 0;

    menu.map(async (category) => {

        const menuLength = menu.length;

        const options = {
            ...apiConfig(),
            method: 'PUT',
            body: JSON.stringify(category)
        }
        const response = await fetch(`${apiUrl}/category/${category._id}`, options)
        let data = await response.json()
        if (response.ok) {
            console.log("It got sent")
            sentRequests++;
            console.log("Printing sentRequests");
            console.log(sentRequests);
            if(sentRequests === menuLength) {
                console.log("All the requests have been sent");
            }
        } else {
            alert(data.error)
        }
    });

    dispatch({ type: FETCH_CATEGORY_RANKS, menu });
}

menu.types.js: menu.types.js:

export const INCREASE_CATEGORY_RANK = "INCREASE_CATEGORY_RANK";
export const DECREASE_CATEGORY_RANK = "DECREASE_CATEGORY_RANK";
export const FETCH_CATEGORY_RANKS = "FETCH_CATEGORY_RANKS";

menu.reducer.js: menu.reducer.js:

// import INITIAL_STATE from './menu.data';
import { INCREASE_CATEGORY_RANK, DECREASE_CATEGORY_RANK, FETCH_CATEGORY_RANKS } from './menu.types';

const INITIAL_STATE = []


export default (state = INITIAL_STATE, action) => {
    switch (action.type) {

        case INCREASE_CATEGORY_RANK: {
            console.log("Went into increase category rank");

            if(action.categoryClicked === false) {
                return state;
            }

            const menuArray = [...state];

            var index = menuArray.map(category => category._id).indexOf(action.category._id);

            //if it's the first element in array it won't move up
            if(index === 0) {
                return state;
            } else {
                const temp = menuArray[index];
                menuArray[index] = menuArray[index - 1];
                menuArray[index - 1] = temp;


                var newrank = 0;

                menuArray.forEach(category => {
                     category.rank = newrank++;
                });


                return menuArray;
            }

        }
        case DECREASE_CATEGORY_RANK: {
            console.log("Went into decrease category rank");

            if(action.categoryClicked === false) {
                return state;
            }

            const menuArray = [...state];

            console.log(menuArray);

            var index = menuArray.map(category => category._id).indexOf(action.category._id);

            //if it's the last element in the array, it won't move down
            if(index === menuArray.length - 1) {
                return state;
            } else {
                const temp = menuArray[index];
                menuArray[index] = menuArray[index + 1];
                menuArray[index + 1] = temp;


                var newrank = 0;

                menuArray.forEach(category => {
                    category.rank = newrank++;
                });


                return menuArray;
            }
        }
        case FETCH_CATEGORY_RANKS:
            return state;
        default:
            return state;
    }
}

In my CategoryArrows component I have a state property called isSending which is set to false .在我的 CategoryArrows 组件中,我有一个名为isSending的 state 属性,该属性设置为false In my fetchCategoryRanks action creator, I am sending information about categories from the menu array in the state to a server using fetch .在我的fetchCategoryRanks动作创建器中,我使用fetch从 state 中的菜单数组向服务器发送有关类别的信息。

I would like to be able to set the isSending property from the CategoryArrows component to true or false , depending on certain conditions in the function fetchCategoryRanks .我希望能够将CategoryArrows组件中的isSending属性设置为truefalse ,具体取决于 function fetchCategoryRanks中的某些条件。

However, I am not sure what the best way to do this is.但是,我不确定最好的方法是什么。 Any insights are appreciated.任何见解都值得赞赏。

First way第一种方式

You can change internal state by sending a callback function to your axios api call.您可以通过将回调 function 发送到您的 axios Z8A5DA52ED120577D359E 调用来更改内部 state。 Before the axios request starts you can call that callback function from axios api function to set isSending=true and after request completed again call callback function to set isSending=false . Before the axios request starts you can call that callback function from axios api function to set isSending=true and after request completed again call callback function to set isSending=false . Callback function implementation must be in component from where you are calling axios api.回调 function 实现必须在您调用 axios api 的组件中。

Api call Api 来电

this.props.fetchCategoryRanks(this.props.menu, (response) => {
    if (isRequestStart) {
        this.setState({
            isSending: true
        });
    }
    if (!isRequestStart) {
        this.setState({
            isSending: false
        });
    }
});

Below is your fetch request以下是您的获取请求

export const fetchCategoryRanks = (menu, callback) => async dispatch => {
    var sentRequests = 0;
    menu.map(async (category) => {
        const menuLength = menu.length;
        callback({
            isRequestStart: true
        });
        const options = {
            ...apiConfig(),
            method: 'PUT',
            body: JSON.stringify(category)
        }
        const response = await
        fetch(`${apiUrl}/category/${category._id}`, options)
        let data = await response.json()
        if (response.ok) {
            callback({
                isRequestStart: false
            });
            console.log("It got sent")
            sentRequests++;
            console.log("Printing sentRequests");
            console.log(sentRequests);
            if (sentRequests === menuLength) {
                console.log("All the requests have been sent");
            }
        } else {
            alert(data.error);
            callback({
                isRequestStart: false
            });
        }
    });
    dispatch({
        type: FETCH_CATEGORY_RANKS,
        menu
    });
}

Second way第二种方式

You can use a reducer where you can set initial state of isSending by dispatching a function from the axios api, calling the dispatch function same as above. You can use a reducer where you can set initial state of isSending by dispatching a function from the axios api, calling the dispatch function same as above. And you can use that reducer state into your component.您可以将减速器 state 用于您的组件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM