React + Redux PUT api-запрос для редактирования данных в моем хранилище redux

Мое приложение использует redux для хранения данных из внутреннего API внутри редуктора сущностей хранилища redux, например, объект данных MEMBER, который совместно используется несколькими компонентами в приложении для отображения сведений о членах. Теперь я реализую компонент EditProfile, который должен брать данные из формы, отправлять их как запрос PUT в серверный API, и если запрос завершился успешно (Готово до сих пор) обновить текущую сущность профиля участника в магазине redux. Я пытаюсь найти что-то вроде "лучшей практики", чтобы достичь этого обновления магазина redux. Я реализовал базовое промежуточное ПО api (похожее на пример реального приложения Redux), но я не совсем уверен, как добраться до части с обновлением состояния.

Мой backend api возвращает после запроса PUT только код состояния и причину (в случае ошибки) или memberId (в случае успеха). Я не могу изменить внутреннюю конечную точку, чтобы вернуть новый объект профиля участника, потому что у нас есть еще один «глобальный» сервер помимо нашего веб-сервера, который работает так же, как этот, и я не могу его изменить.

Поэтому я думаю, что мне нужно будет сохранить данные из формы (response-final-form), и в случае успешного ответа, который содержит memberId (из бэкэнда), используйте эти данные для обновления текущего объекта хранилища Redux (профиля участника).

Я думал о сохранении данных запроса на обновление в хранилище entity reducer -> с таким ключом, как UPDATING_MEMBER_PROFILE, и запрос идентификатора завершается успешно, объедините эти два объекта в один и очистите часть UPDATING_. У вас есть какие-нибудь предложения, пожалуйста?

ОБНОВЛЕНИЕ:

Чтобы вызвать API в моем коде, у меня есть такие действия, как:

memberAction.js

export const updateProfile = values => ({
type: API,
  payload: {
    url: "/members/update",
    method: "PUT",
    data: values,
    meta: {
      label: MEMBER_PROFILE,
      success: [], // action callbacks onSuccess
      error: [] // action callbacks onError
    }
  }
});

тогда мое промежуточное ПО API заботится о action.type === API и генерирует действия для типов API_REQUEST, API_SUCCESS и API_ERROR с сущностью и меткой из первых действий fetchProfile. Это выглядит как:

apiMiddleware.js

...getting Info from origin action about request here

next(action);
dispatch(apiRequest(entity, label));

return callApi(url, method, data)
  .then(response => {
    dispatch(apiSuccess(response.status, response, label));
    dispatch(success(response)); // Dispatch callbacks...
  })
  .catch(error => {
    dispatch(apiError(response.status, error, label));
    dispatch(error(response)); // Dispatch callbacks...
  });

и после сервера промежуточного программного обеспечения и отправки других действий мой редуктор api будет назначать данные из API для хранения по сущности, например:

apiReducer.js

const apiEntitiesReducer = (state = {}, action) => {
  switch (action.type) {
    case API_REQUEST: 
      return {
        ...state,
        [action.payload.label]: {
          error: false,
          data: null
        }
      };
    case API_ERROR:
    case API_SUCCESS:
      return {
        ...state,
        [action.payload.label]: {
          error: action.isError,
          data: action.payload.data
        }
      };
    default:
      return state;
  }
};

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


person sbqq    schedule 26.09.2018    source источник


Ответы (1)


Вы на правильном пути. Попробуйте отправить одно действие для отправки запроса к API, а затем (после успеха) отправьте другое действие для обновления вашего магазина. Что-то подобное

profile.js:

export const updateProfile = newMemberProfile => { //your action, using thunk here
  return dispatch => {
   fetch(UPDATE_URL, {
        method: "PUT",
        body: JSON.stringify(newMemberProfile),            
    })
    .catch(err => {
      console.log(err);
      alert("Profile update failed, please try again!");
    })
    .then(res => {
        dispatch(memberProfileUpdated(newMemberProfile));
    });
   }
}

export const memberProfileUpdated = newMemberProfile => {
  return {
    type: UPDATING_MEMBER_PROFILE,
    newMemberProfile
  };
};

Затем добавьте редуктор для этой константы (поместите все константы и редукторы в отдельные файлы для ясности) reducer.js:

const initialState = {
    memberProfile: null,
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case UPDATING_MEMBER_PROFILE:
      return {
        ...state,
        memberProfile: action.newMemberProfile
      };
    default:
      return state;
  }
};

export default reducer;

Не забудьте прописать редуктор в своей конфигурации! Надеюсь, это поможет!

person Nikolay Tomitov    schedule 26.09.2018
comment
Здравствуйте, Николай! Большое вам спасибо за ваш ответ. Я просто не могу обобщить его достаточно для подхода, который я использую, и это нормально, потому что я ничего не писал о своем подходе ... Я обновил свой вопрос о происхождении некоторыми примерами кода моего подхода. Могу я попросить вас взглянуть на это? Большое спасибо! - person sbqq; 26.09.2018
comment
Это немного беспорядочно, но, насколько я понимаю, action.payload.data - это ваш новый профиль. Просто отправьте другое действие для обновления профиля (как в моем примере) и с помощью другого редуктора установите новый профиль. И: dispatch(apiSuccess(response.status, response, label)); - ›возможно, вам придется заменить второй аргумент на data, поскольку в случае успеха вам не нужен ответ от сервера, но вы должны передать новый профиль редуктору, чтобы обновить ваш магазин. - person Nikolay Tomitov; 26.09.2018
comment
Большое вам спасибо :) Я постараюсь поиграть с ним столько, сколько потребуется, чтобы он заработал. - person sbqq; 26.09.2018
comment
У меня такой же вопрос, но часть состояния - это массив. Как с этим бороться? Я пробовал filter (), но он не работает. - person bannedFromAskingQuestions; 01.06.2020
comment
якш что именно ты хочешь сделать? - person Nikolay Tomitov; 02.06.2020