Redux: opinie/przykłady jak zrobić backend persistence?

Zastanawiam się, jak ludzie korzystający z Redux zbliżają się do swojej uporczywości. W szczególności, czy przechowujesz "akcje" w bazie danych, czy przechowujesz tylko ostatni znany stan aplikacji?

Jeśli przechowujesz akcje, czy po prostu żądasz ich od serwera, a następnie odtwarzasz je wszystkie, gdy dana strona się ładuje? Czy nie może to prowadzić do problemów z wydajnością w aplikacji na dużą skalę, w której istnieje wiele działań?

Jeśli czy przechowując tylko "aktualny stan", w jaki sposób faktycznie utrzymujesz ten stan w danym momencie, gdy działania zdarzają się na kliencie?

Czy ktoś ma jakieś przykłady kodu jak podłączają Redux Redux do backend storage API?

Wiem, że to bardzo "to zależy od twojej aplikacji" pytanie typu, ale po prostu zastanawiam się nad kilkoma pomysłami tutaj i staram się poczuć, jak tego rodzaju "bezpaństwowa" architektura może działać w pełnym sensie stosu.

Dziękuję wszystkim.

Author: Lee, 2015-10-05

2 answers

Zdecydowanie utrzymaj stan swoich reduktorów!

Jeśli zamiast tego utrzymałbyś sekwencję działań, nigdy nie byłbyś w stanie zmodyfikować swoich działań w interfejsie użytkownika bez majstrowania w bazie danych prod.

Przykład: persist one Reducer ' s state to a server

Zaczniemy od trzech dodatkowych typów akcji:

// actions: 'SAVE', 'SAVE_SUCCESS', 'SAVE_ERROR'

Używam redux-thunk do wykonywania wywołań asynchronicznych serwera: oznacza to, że jedna funkcja kreatora akcji może dispatch dodatkowe akcje i sprawdzenie aktualnego stanu.

Kreator akcji save natychmiast wysyła jedną akcję (aby można było pokazać spinner lub Wyłączyć przycisk "Zapisz" w interfejsie użytkownika). Następnie wysyła SAVE_SUCCESS lub SAVE_ERROR akcje po zakończeniu żądania POST.

var actionCreators = {
  save: () => {
    return (dispatch, getState) => {
      var currentState = getState();
      var interestingBits = extractInterestingBitsFromState(currentState);

      dispatch({type: 'SAVE'});

      window.fetch(someUrl, {
        method: 'POST',
        body: JSON.stringify(interestingBits)
      })
      .then(checkStatus) // from https://github.com/github/fetch#handling-http-error-statuses
      .then((response) => response.json())
      .then((json) => dispatch actionCreators.saveSuccess(json.someResponseValue))
      .catch((error) =>
        console.error(error)
        dispatch actionCreators.saveError(error)
      );
    }
  },

  saveSuccess: (someResponseValue) => return {type: 'SAVE_SUCCESS', someResponseValue},

  saveError: (error) => return {type: 'SAVE_ERROR', error},

  // other real actions here
};

(N. B. $.ajax będzie całkowicie działać w miejsce window.fetch rzeczy, po prostu wolę nie ładować całego jQuery dla jednej funkcji!)

Reduktor po prostu śledzi każdy wybitny serwer Prośba.

function reducer(state, action) {
  switch (action.type) {
    case 'SAVE':
      return Object.assign {}, state, {savePending: true, saveSucceeded: null, saveError: null}
      break;
    case 'SAVE_SUCCESS':
      return Object.assign {}, state, {savePending: false, saveSucceeded: true, saveError: false}
      break;
    case 'SAVE_ERROR': 
      return Object.assign {}, state, {savePending: false, saveSucceeded: false, saveError: true}
      break;

    // real actions handled here
  }
}

Prawdopodobnie będziesz chciał zrobić coś z someResponseValue, które wróciło z serwera-może to identyfikator nowo utworzonej jednostki itp itd.

Mam nadzieję, że to pomoże, to działa ładnie jak na razie dla mnie!

 34
Author: Dan Fox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-10 14:46:55

Zdecydowanie Kontynuuj działania!

to tylko kontrprzykład, dodając do komentarza dana Fitcha w poprzedniej odpowiedzi.

Jeśli utrzymasz swój stan, nigdy nie będziesz w stanie zmodyfikować swojego stanu bez zmiany kolumn i tabel w bazie danych. Stan pokazuje Ci tylko jak jest teraz, nie możesz odbudować poprzedniego stanu i nie będziesz wiedział, które fakty się wydarzyły.

Przykład: persist an action to a Serwer

Twój action jest już "typem" i "ładunkiem", i to prawdopodobnie wszystko, czego potrzebujesz w architekturze opartej na zdarzeniach/Event-Sourcing.

Możesz zadzwonić do swojego zaplecza i wysłać działania wewnątrz actionCreator (Zobacz odpowiedź dana Foxa ).

Inną alternatywą jest użycie middleware do filtrowania działań, które mają być utrzymywane, i wysyłania ich do zaplecza, a opcjonalnie wysyłania nowych zdarzeń do sklepu.

const persistenceActionTypes = ['CREATE_ORDER', 'UPDATE_PROFILE'];
// notPersistenceActionTypes = ['ADD_ITEM_TO_CART', 'REMOVE_ITEM_FROM_CART', 'NAVIGATE']

const persistenceMiddleware = store => dispatch => action => {
  const result = dispatch(action);
  if (persistenceActionTypes.indexOf(action.type) > -1) {
  // or maybe you could filter by the payload. Ex:
  // if (action.timestamp) {
      sendToBackend(store, action);
  }
  return result;
}

const sendToBackend = (store, action) => {
  const interestingBits = extractInterestingBitsFromAction(action);
  // déjà vu
  window.fetch(someUrl, {
    method: 'POST',
    body: JSON.stringify(interestingBits)
  })
  .then(checkStatus)
  .then(response => response.json())
  .then(json => {
    store.dispatch(actionCreators.saveSuccess(json.someResponseValue));
  })
  .catch(error => {
    console.error(error)
    store.dispatch(actionCreators.saveError(error))
  });
}
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk';

createStore(
  yourReducer,
  aPreloadedState,
  applyMiddleware(thunk, persistenceMiddleware)
)

(ty może również użyć oprogramowania pośredniczącego do wysłania bieżącego stanu do kopii zapasowej. Call store.getState().)

Twoja aplikacja już wie, jak przekształcić akcje w stan z reducers, możesz więc również pobierać akcje z backendu.

 1
Author: Matruskan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-16 14:30:22