React-Redux: отправка данных о нескольких обновленных категориях при отправке действия с использованием fetch - PullRequest
0 голосов
/ 19 апреля 2020

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

menu.reducer. js:

import { GET_MENU, INCREASE_CATEGORY_RANK, DECREASE_CATEGORY_RANK } from './menu.types';

const INITIAL_STATE = []


export default (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case GET_MENU:
            return [ ...action.payload ];

        case INCREASE_CATEGORY_RANK: {
            const menuArray = [...state];

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

            if(index === 0) {
                return state;
            } else {
                const temp = menuArray[index];
                menuArray[index] = menuArray[index - 1];
                menuArray[index - 1] = temp;

                //update the ranks.
                if(action.payload.rank !== -1) {
                    const temprank = menuArray[index].rank;
                    menuArray[index].rank = menuArray[index - 1].rank;
                    menuArray[index - 1].rank = temprank;

                } else {
                    var newrank = 0;

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

                return menuArray;
            }
        }
        case DECREASE_CATEGORY_RANK: {
            const menuArray = [...state];

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

            if(index === menuArray.length - 1) {
                return state;
            } else {
                const temp = menuArray[index];
                menuArray[index] = menuArray[index + 1];
                menuArray[index + 1] = temp;

                //update the ranks.
                if(action.payload.rank !== -1) {
                    const temprank = menuArray[index].rank;
                    menuArray[index].rank = menuArray[index + 1].rank;
                    menuArray[index + 1].rank = temprank;

                } else {
                    var newrank = 0;

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

                return menuArray;
            }
        }
        default:
            return state;
    }
}

menu.actions. js:

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

export const getMenu = () => async dispatch => {
    const response = await fetch(`${apiUrl}/menu`);
    if (response.ok) {
        const menuData = await response.json();
        dispatch({ type: GET_MENU, payload: menuData })
    }
}

export const increaseCategoryRank = category => dispatch => {
    dispatch({ type: INCREASE_CATEGORY_RANK, payload: category })
    fetch(`${apiUrl}/category/${category._id}`, {
        ...apiConfig(),
        method: 'PUT',
        body: JSON.stringify(category)
    })

}

export const decreaseCategoryRank = category => dispatch => {
    dispatch({ type: DECREASE_CATEGORY_RANK, payload: category })
    fetch(`${apiUrl}/category/${category._id}`, {
        ...apiConfig(),
        method: 'PUT',
        body: JSON.stringify(category)
    })
}

menu.component. jsx:

import React, { Component } from 'react';
import { connect } from 'react-redux';

import MenuCategory from '../../components/menu-category/menu-category.component'
import NewCategoryButton from '../../components/new-category-button/new-category-button.component';
import Loading from '../../components/loading/loading.component';
import { getMenu } from '../../redux/menu/menu.actions';
import { MANAGER } from '../../redux/user/user.staff-types';

import './menu.styles.scss';

class MenuPage extends Component {

     async componentDidMount() {
        await this.props.getMenu()
     }

    render() {

        const isMenuLoaded = !!this.props.menu.length;
        const isManager = this.props.currentUser && this.props.currentUser.type === MANAGER;

        return (
            <div className='menu-page'>
                {isMenuLoaded ? this.props.menu.map(category => <MenuCategory key={category._id} {...category} />) : <Loading />}
                <div className='menu-button'>
                    {isMenuLoaded && isManager ? <NewCategoryButton /> : null}
                </div>
            </div>
        )
    }
}

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


export default connect(mapStateToProps, { getMenu })(MenuPage);

category-arrow.component.jsx:

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

class CategoryArrows extends Component {

    render() {

        const { category, increaseCategoryRank, decreaseCategoryRank } = this.props;

        return (
            <div class="arrows-container">
                <div class="up-arrow" onClick={() => this.props.increaseCategoryRank(category)}></div>
                <div class="category-rank">
                    <p>{category.rank}</p>
                </div>
                <div class="down-arrow" onClick={() => this.props.decreaseCategoryRank(category)}></div>
            </div>
        )
    }
}

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

В состоянии Redux существует массив menu, который имеет следующее:

enter image description here

В приведенном выше коде компонент CategoryArrows отображается в компоненте MenuCategory. Компонент MenuCategory отображается в компоненте MenuPage.

При щелчке по элементам up-arrow и down-arrow в компоненте CategoryArrows отправляются действия INCREASE_CATEGORY_RANK и DECREASE_CATEGORY_RANK соответственно. В этих действиях я изменяю массив меню из состояния и обновляю ранги категорий меню.

Однако я также хочу отправить обновленную информацию о категориях на сервер. Я делаю это через fetch и делаю запрос PUT. Однако в запросе на выборку я могу отправлять на сервер только данные об одной обновленной категории меню. Это потому, что я могу использовать только конечную точку ${apiUrl}/category/${category._id} в запросе на выборку, поэтому я могу отправлять данные только по одной категории меню за один раз.

Я хотел бы отправлять данные обо всех категориях, которые были обновлены (т. е. изменились ли их ранги) в случаях INCREASE_CATEGORY_RANK и DECREASE_CATEGORY_RANK в моем коде Reducer в запросе на выборку.

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

...