Я работаю над приложением 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](https://i.stack.imgur.com/wINMi.png)
В приведенном выше коде компонент 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 в запросе на выборку.
Однако я не уверен, каков наилучший способ сделать это. Любые идеи приветствуются.