Как я могу создать вспомогательный метод, который принимает параметр для фильтрации данных из хранилища redux? - PullRequest
1 голос
/ 09 июля 2020

В моем приложении response / redux / redux-thunk у меня есть редуктор, который управляет состоянием, содержащим список вещей, похожих на:

state = {
  stuff: [
    {
      id: 1,
      color: "blue",
      shape: "square"
    },
    {
      id: 2,
      color: "red",
      shape: "circle"
    },
    {
      id: 3,
      color: "yellow",
      shape: "square"
    },
  ]
};

Я хочу создать вспомогательные функции, которые я могу использовать в своем приложении которые возвращают отфильтрованные списки вещей из магазина на основе аргумента, переданного в функцию. Например:

getStuffByShape("square");  // returns array with stuff 1 and 3
getStuffByColor("red"); // returns array with stuff 2

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

Я читал о создании селекторов и пакета reselect, но примеры показывать только функции, принимающие параметр состояния, и мне непонятно, могу ли я передать дополнительный произвольный параметр.

Я могу передавать состояние в качестве аргумента от подключенного компонента, но я могу использовать их функции в других местах, например, другие вспомогательные функции.

1 Ответ

0 голосов
/ 09 июля 2020

Вы можете создать параметризованный селектор , мой предпочтительный метод - каррированный, который вы можете запоминать:

const { Provider, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const { createSelector } = Reselect;

const initialState = {
  stuff: [
    {
      id: 1,
      color: 'blue',
      shape: 'square',
    },
    {
      id: 2,
      color: 'red',
      shape: 'circle',
    },
    {
      id: 3,
      color: 'yellow',
      shape: 'square',
    },
  ],
};
const reducer = (state) => state;
//helper
const createFilterBy = (field, value) => (item) =>
  value ? item[field] === value : true;
//selectors
const selectStuff = (state) => state.stuff;
const createSelectFiltered = (filterFn) =>
  createSelector([selectStuff], (stuff) =>
    stuff.filter(filterFn)
  );
const createSelectByColor = (color) =>
  createSelector(
    [createSelectFiltered(createFilterBy('color', color))],
    (x) => x
  );
const createSelectByShape = (shape) =>
  createSelector(
    [createSelectFiltered(createFilterBy('shape', shape))],
    (x) => x
  );
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(() => (next) => (action) =>
      next(action)
    )
  )
);
const List = React.memo(function List({ items }) {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>{JSON.stringify(item)}</li>
      ))}
    </ul>
  );
});
const SelectList = React.memo(function SelectList({
  label,
  value,
  setter,
  options,
}) {
  return (
    <label>
      {label}
      <select
        value={value}
        onChange={({ target: { value } }) =>
          setter(value === 'all' ? undefined : value)
        }
      >
        <option value="all">all</option>
        {options.map((option) => (
          <option key={option} value={option}>
            {option}
          </option>
        ))}
      </select>
    </label>
  );
});
const colors = ['blue', 'red', 'yellow'];
const shapes = ['square', 'circle'];
const App = () => {
  const [color, setColor] = React.useState();
  const [shape, setShape] = React.useState();
  const selectByColor = React.useMemo(
    () => createSelectByColor(color),
    [color]
  );
  const selectByShape = React.useMemo(
    () => createSelectByShape(shape),
    [shape]
  );
  const byColor = useSelector(selectByColor);
  const byShape = useSelector(selectByShape);
  return (
    <div>
      <div>
        <SelectList
          label="color"
          value={color}
          setter={setColor}
          options={colors}
        />
        <SelectList
          label="shape"
          value={shape}
          setter={setShape}
          options={shapes}
        />
      </div>
      <div>
        <h4>color</h4>
        <List items={byColor} />
        <h4>shape</h4>
        <List items={byShape} />
      </div>
    </div>
  );
};

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>
<div id="root"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...