Как изменить свойство внутреннего состояния компонента в функции создателя действия - PullRequest
1 голос
/ 22 апреля 2020

Я работаю над приложением React и использую Redux для хранения состояния. У меня есть следующий код:

category-arrow.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:

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:

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:

// 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;
    }
}

В моем компоненте CategoryArrows у меня есть свойство состояния с именем isSending, которое установлено в false , В моем fetchCategoryRanks создателе действий я отправляю информацию о категориях из массива меню в состоянии на сервер, используя fetch.

Я хотел бы иметь возможность установить свойство isSending для компонента CategoryArrows на true или false, в зависимости от определенных условий в функции fetchCategoryRanks.

Однако я не уверен, что лучший способ сделать это. Любые идеи приветствуются.

1 Ответ

1 голос
/ 22 апреля 2020

Первый способ

Вы можете изменить внутреннее состояние, отправив функцию обратного вызова на ваш вызов ios API. Перед запуском запроса ax ios вы можете вызвать эту функцию обратного вызова из функции api ax ios для установки isSending=true, а после завершения запроса снова вызвать функцию обратного вызова для установки isSending=false. Реализация функции обратного вызова должна быть в компоненте, откуда вы вызываете ax ios api.

Api call

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

Ниже приведен ваш запрос на выборку

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
    });
}

Второй способ

Вы можете использовать редуктор, в котором вы можете установить начальное состояние isSending, отправив функцию с топора ios API, вызывая функцию отправки, как описано выше. И вы можете использовать это состояние редуктора в вашем компоненте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...