Где я должен обновлять отфильтрованные данные в саге, повторном выборе или редукторах? - PullRequest
0 голосов
/ 19 января 2020

Я сейчас использую reselect, redux-sagas и редукторы. У меня есть filterParameter в состоянии, в котором хранятся значения FilterParameter filterReducer.js:

initialState = {
  filteredParameters: { ... } // null by default
}

Отфильтрованные данные используются в моем компоненте filters.js:

// On change function
  const statusChange = event => {
    event.preventDefault();
    const { name, value } = event.target;

    setFilterParameters({ ...filterParameters, [name]: parseInt(value) });
  };

// Render
 {statuses && (
        <select name="statusId" onChange={statusChange}>
          <option>All</option>
          {statuses.map(status => (
            <option
              selected={
                filteredParameters && filteredParameters.statusId === status.id
              }
              key={status.id}
              name={status.name}
              value={status.id}
            >
              {status.icon} {status.name}
            </option>
          ))}
        </select>
      )}

// MapDispatchToProps
const mapDispatchToProps = dispatch => ({
  filterIdeas: parameters => dispatch(filterIdeas(parameters)),
  fetchCategories: () => dispatch(fetchCategoriesStart())
});

Тогда у меня есть saga настройка для перехвата этого действия в filter.sagas.js:

function* filterCurrentIdeas({ payload: filteredParameters }) {
  try {
    yield put(setFilterParameters(filteredParameters));
    const ideas = yield select(selectBoardIdeasItems);

    // Custom function that does the filtering handling, this is shown below 

    const filterResults = yield call(
      filterIdeasByStatus,
      ideas,
      filteredParameters
    ); 
    yield put(filterIdeasSuccess(filterResults)); // This then gets fed into the reducer
  } catch (err) {
    console.log(err);
    return;
  }
}

Вот мой редуктор filter.reducer.js

    case BoardActionTypes.FILTER_IDEAS_SUCCESS:
      return {
        ...state,
        filteredItems: action.payload
      };

Вот специальный помощник для фильтрации filter.utils.js:

export const filterIdeasByStatus = (ideas, filter) => {
  const { statusId, categoryId, orderBy, query } = filter;
  const orderedIdeas = orderBy ? _.orderBy(ideas, ["voteCount"]) : ideas;
  const regex = new RegExp(`${query}`, "gmius");

  const filtered = orderedIdeas.filter(
    idea =>
      (!statusId || (statusId && idea.IdeaStatus.id === statusId)) &&
      (!categoryId ||
        (categoryId && _.includes(idea.categoryIds, categoryId))) &&
      (!query || (query && idea.title.match(regex)))
  );

  return convertIdeasToObject(filtered);
};

В настоящее время все это работает, но я делаю это неправильно или есть гораздо лучший подход или руководство, которое может дать мне лучший пример?

Заранее спасибо!

1 Ответ

0 голосов
/ 20 января 2020

Вспомогательная функция filterIdeasByStatus - отличная практика для поддержания вашего кода модульным и организованным.

Однако, если setFilterParameters является действием:

setFilterParameters({ ...filterParameters, [name]: parseInt(value) });

Почему вы звоните дважды?

  1. В filter.sagas.js в filterCurrentIdeas саге
  2. В filters.js компоненте

Обычно вы будете хотите отправить действие на statusChange и позволить саге фильтровать элементы (как вы это сделали). Но вызов одного и того же действия дважды может вызвать побочные эффекты.

Тщательный совет: помните, что пространство имен компонента React обычно пишется с большой буквы, то есть фильтры. js должно быть Filters. js.

You также можете искать лучшие практики и / или запрашивать обратную связь в Обзор кода обмена стека

Надеюсь, вы получили несколько идей:)

...