Как вы фильтруете данные по категориям, используя действие и редуктор в редуксе? - PullRequest
1 голос
/ 10 октября 2019

Я создаю фильтр, где пользователи могут фильтровать данные, по какому типу категории они хотели бы, например, рестораны, бары, кафе и т. Д. Пользователь использует фильтр, выбирая, является ли категория истинной дляfalse (т. е. отображается эта конкретная категория или нет), которая затем отправляется моему действию и редуктору. Как бы вы установили редуктор для фильтрации данных, чтобы отображались только истинные категории?

Это мой файл filter.js (с магазином и едой, которые имеют значение true или false):

onButtonPress() {
    const { shop, food } 
    = this.state;

this.props.filterRecommendations({ shop, food });

Это мой файл action.js:

export const filterRecommendations = ({ shop, food}) => {
    return {
        type: FILTER_RECOMMENDATIONS_BY_TYPE,
        payload: { shop, food }
    };
};

Это мой файл reducer.js:

export const reducer = (state = INITIAL_STATE, action) => {
    switch (action.type) {
    case FILTER_RECOMMENDATIONS_BY_TYPE:
        return {
            ...state,
                myRecommendations: state.myRecommendations.filter(
            item => item.type === action.payload
            )
        };
};

Данные выглядят так:

myRecommendations: [
    {
      id: '1',
      name: 'Yes Food',
      type: 'food'
    },
            {
      id: '2',
      name: 'Yes Shop',
      type: 'shop'
    },
]

То, что приведено выше, это просто очистка всех данных.

Ответы [ 3 ]

1 голос
/ 10 октября 2019

@ Предложение Юви использовать селектор - хорошая идея. Это позволяет вам фильтровать ваш список без изменения состояния вашего редуктора. Это важно в вашем случае, потому что при вашем текущем подходе каждый раз, когда вы меняете фильтр, вы удаляете больше данных из своего состояния, а именно:

  1. Выбор food> myRecommendations содержит только food элементовтеперь
  2. Выберите shop> myRecommendations пусто, потому что shop элементов было удалено выше

Redux содержит документацию, объясняющую, как это сделать здесь . Без селекторов вам потребуется способ перезаполнения вашего состояния myRecommendations между вызовами фильтра.

Использование чего-то вроде reselect (см. здесь ) поможет повысить производительность, запомнив селектор,но основная концепция заключается в следующем:

  1. Сохранение неотфильтрованных результатов в вашем состоянии
  2. Сохранение выбранного фильтра как его собственного состояния
  3. Фильтрация данных там, где они необходимыв состоянии фильтра

то есть:

filter.js - Установите выбранный фильтр

onButtonPress() {
  const { shop, food } = this.state;
  this.props.setRecommendationsFilter({ shop, food });
}

Где бы вы не определилиимена ваших действий

const SET_RECOMMENDATIONS_FILTER = 'SET_RECOMMENDATIONS_FILTER';

action.js

export const setRecommendationsFilter = (filter) => {
  return {
    type: SET_RECOMMENDATIONS_FILTER,
    filter,
};

reducer.js - Сохранить выбранный фильтр без измененияданные рекомендаций

export const reducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case SET_RECOMMENDATIONS_FILTER: {
      return {
        ...state,
        recommendationsFilter: action.filter,
      };
    }
  }
};

Где вы используете отфильтрованные рекомендации - Это концепция селектора

// 1. Bring in myRecommendations and recommendationsFilter from redux

// 2. Filter
/**
 * Get a filtered list of items, where the filter that matches
 * the recommendation 'type' is set to 'true'
 */
const filteredRecommendations = myRecommendations.filter(
  (item) => recommendationsFilter[item.type]
);

// 3. Now use filteredRecommendations as you would have used myRecommendations

При использовании чего-то вроде повторного выбора вы должны поставить логикусоздает filteredRecommendations вместе с логикой для получения нужных вам данных отвыборщик, а затем используйте этот селектор в вашем mapStateToProps (как описано здесь ).

1 голос
/ 10 октября 2019

Вы можете получить доступ к ключам объекта, отфильтровав данные:

state.myRecommendations.filter(item => action.payload[item.type])

0 голосов
/ 10 октября 2019

Это может работать для вас

При нажатии кнопки вы можете передать массив для всех фильтров

onButtonPress() {
    const { shop, food } 
    = this.state;

this.props.filterRecommendations([shop, food ]);
export const filterRecommendations = (recommendationList ) => {
    return {
        type: FILTER_RECOMMENDATIONS_BY_TYPE,
        payload: recommendationList
    };
};
export const reducer = (state = INITIAL_STATE, action) => {
    switch (action.type) {
    case FILTER_RECOMMENDATIONS_BY_TYPE:
        return {
            ...state,
                myRecommendations: state.myRecommendations.filter(
            item => action.payload.includes(item.type)
            )
        };
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...