Redux pre process store перед mapStateToProps? - PullRequest
0 голосов
/ 09 января 2020

У меня есть магазин с несколькими командами.

    const store = {
       selectedTeamId: 'team1';
       teams: {
          team1: { ... },
          team2: { ... },
          team3: { ... },
       },
    };

В любой момент времени устанавливается teamId.

Теперь, учитывая, что я должен выбрать команду, используя каждый идентификатор Когда я звоню mapStateToProps(), я чувствую, что это громоздко.

Вместо того, чтобы делать это все время:


    mapStateToProps({ selectedTeamId, teams }) {
       return {
           team: teams[selectedTeamId],
       }
    }

Могу ли я предварительно обработать магазин с использованием некоторого промежуточного программного обеспечения вместо повторения этого шаблон в состоянии карты для реквизита?

Ответы [ 3 ]

2 голосов
/ 09 января 2020

Подход, предлагаемый Redux docs, состоит в том, чтобы создать селектор для текущей активной команды и повторно использовать его во всех компонентах

// selector itself is a pure function of state
// usually put in separate file, or in file with reducer
const activeTeamSelector = state => state.teams.teams[state.teams.selectedTeamId]


// in connect
const mapStateToProps = (state) => ({
  activeTeam: activeTeamSelector(state),
})

Это, конечно, если вы используете ОбъединитьReducers и команды Редуктор называется teams в состоянии. Если вы этого не сделаете, и selectedTeamId и teams содержатся прямо в вашем магазине, будет работать следующее

const activeTeamSelector = state => state.teams[state.selectedTeamId]

Обратите внимание, что мне нужно было только изменить селектор для этого, а не каждый mapStateToProps во всех компонентах

подробнее о Нормализация состояния хранилища и Вычисление производных данных в Redux docs

1 голос
/ 09 января 2020

Я в конечном итоге использовал reselect, благодаря рекомендации @ jank.

Одна из вещей, которые я хотел сделать, это абстрагироваться от необходимости появления селекторов в mapStateToProps. Для этого я обернул редуксом connect. Это позволяет вставить функцию denormalizer перед mapStateToProps.

import { connect } from 'react-redux';
import { createSelector } from 'reselect';

const getActiveTeamId = state => state.activeTeamId;
const getAllTeams = state => state.teams;

const teamSelector = createSelector(
  getActiveTeamId,
  getAllTeams,
  (activeTeamId, teams) => teams[activeTeamId],
);

function denormalizer(mapStateToProps) {
  return state => {
    return mapStateToProps({ team: teamSelector(state) });
  };
}

export default function reConnect(mapStateToProps = null, actions = null) {
  const denormalizedMapStateToProps = denormalizer(mapStateToProps);

  return function callConnect(Component) {
    return connect(denormalizedMapStateToProps, actions)(Component);
  };
}

1 голос
/ 09 января 2020

Использование промежуточного программного обеспечения для этого сценария нецелесообразно (если я правильно понял ваш вопрос :)). Я опишу 3 варианта, которые вы можете использовать для достижения этой цели:

Вариант 1

возвращает оба значения selectedTeamId и teams в mapStateToProps, это позволит вам чтобы найти команду, которая вам нужна для каждого выбранного идентификатора:

mapStateToProps({ selectedTeamId, teams }) {
    return {
        selectedTeamId,
        teams
    }
}

Таким образом, вы можете получить доступ к этим реквизитам в render:

render() {
    const { teams, selectedTeamId } = this.props;
    return <Team team={teams.find(team => team.id === selectedTeamId)} />
}

Примечание: <Team /> это просто компонент Я сделал для демонстрации

Вариант 2

Вы можете использовать перебрать библиотеку, чтобы избежать повторного вычисления этого пропета:

import { createSelector } from 'reselect'

const teams = state => state.teams;
const selectedTeamId = state => state.selectedTeamId;

const subtotalSelector = createSelector(
  teams,
  selectedTeamId,
  (teams, selectedTeamId) => items.find(team => team.id === selectedTeamId)
)

Опция 3

Создать действие, которое будет отправлять SELECT_TEAM с teamId

export function setSelectedTeam(id) {
    return { type: types.SELECT_TEAM, payload: id };
}

Создать редуктор для этого типа и вернуть selectedTeam:

[types.SELECT_TEAM]: (state, payload)=> {
    return {
        ...state,
        selectedTeam: state.teams.find(team => team.id === payload.id)
    };
},

Таким образом, вы можете иметь селектор для selectedTeam

export const getSelectedTeam = state => state.selectedTeam;

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...