Неправильно ли использовать полезную нагрузку действия внутри компонента с реакцией-редукцией?

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

Вот пример кода

Состояние

export interface State {
  [requestId: number]: Request;
}
export interface Request {
  status: string;
  error?: string;
}

Действие

export function createRequest(): Action {
  return {
    type: "request",
    payload: {
      requestId: Math.random () // Make a random Id here
    }
  };
}

Редуктор

export function createRequestReducer(state: State): State {
  return {
    ...state,
    ...{ state.payload.requestId: { status: "pending" } }
  }; 
}

Составная часть

interface props {
  getRequestById: (id: number) => Request;
  createRequest: () => number;
}

const component = (props: testProps): JSX.Element => {
  const getRequestById = props.getRequestById;
  const [requestId, setRequestId] = useState(null);
  const [request, setRequest] = useState(null);

  useEffect(() => {
    if (requestId !== null) {
      setRequest(getRequestById(requestId));
    }
  }, [requestId]);

  return <div>The request status is {(request && request.status) || "Not started"}</div>;
}

function mapStateToProps(state: State) {
  return {
    getRequestById: (requestId: number): Request => {
      getRequestById(state, requestId)
    }
  };
}

function mapDispatchToProps(dispatch: Dispatch) {
  return {
    createRequest: (): number => {
      const action = createRequest();
      dispatch(action);
      return action.payload.requestId;
    }
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(component);

Я ожидаю, что это сработает, но это может быть массовый анти-паттерн. Разве это не рекомендуется, и если да, то есть ли альтернатива?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
25
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что ваш подход работает технически совершенно нормально. Только "логически" возможно есть смысл внести некоторые изменения:

Да, «экшн» — это то, что должно быть отправлено редюсеру (и больше нигде не использовано, хотя технически с этим проблем нет).

Но что вы можете сделать:

1. отдельное действие и значения

Внутри функции создания действий вы можете делать все, что захотите.

Таким образом, вы можете создавать и использовать action и requestId отдельно. Технически это то же самое, что и вы, но логически разделенное.

Например.:

function createRequest(){
    const requestId = createUniqueId();
    const action = { type: "request", payload: { requestId: requestId } };
    return {
        requestId: requestId, // <-- request id independent of the action
        action: action,       // <-- action independent of the request id
    };
}

function mapDispatchToProps( dispatch: Dispatch ){
  return {
    createRequest: (): number => {
      const { requestId, action } = createRequest();
      dispatch( action );    // <-- action independent of the request id
      return requestId;      // <-- request id independent of the action
    }
  };
}

2. «диспетчеры действий»

Мне (и, видимо, другим) нравится использовать то, что я называю «диспетчерами действий». Это лишний шаг и больше кода, но я думаю, что когда вы привыкнете к этой концепции, она устранит любые сомнения, где нужно размещать такой код.

Например.:

// Create the action, and nothing else:
const createRequestActionCreator = function( requestId ){
  return { type: "request", payload: { requestId: requestId } };
};

// Preper some data needed to create the action:
const createRequestActionDispatcher = function( dispatch ){
  return function(){
    const requestId = createUniqueId();
    dispatch( createRequestActionCreator( requestId ) );
    return requestId;
  };
};

// 
function mapDispatchToProps( dispatch: Dispatch ) {
  return {
    createRequest: (): number => {
      const requestId = createRequestActionDispatcher( dispatch )();
      return requestId;
    }
  };
}

2.а

Кроме того, вы можете передать такой «диспетчер действий» непосредственно в качестве реквизита, если хотите. В этом случае он в основном заменяет вашу функцию в mapDispatchToProps, но может использоваться повторно, например:

function mapDispatchToProps( dispatch: Dispatch ) {
  return {
    createRequest: createRequestActionDispatcher( dispatch ),
  };
}

2.б

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

const createRequestActionDispatcher = (dispatch: Dispatch) => (maybeSomeValue: MyType) => {
    const requestId = createUniqueId();
    dispatch( createRequestActionCreator( requestId ) );
    return requestId;
};

Примечание:

Обычно я предпочитаю быть последовательным, для чего я должен всегда (или никогда) использовать эти «диспетчеры действий», но я обнаружил, что большую часть времени они мне не нужны, но иногда я нахожу их очень полезными. Так что я на самом деле использую dispatch( myAction ) в некоторых местах и ​​myActionDispatcher(value)(dispatch) в других. Мне это не нравится, но это работает хорошо, и у меня нет лучшей идеи.

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

Francis Bryson 07.04.2022 10:57

Другие вопросы по теме