programing

새로 고침 시 Redux 상태 트리를 유지하려면 어떻게 해야 합니까?

telebox 2023. 4. 2. 10:19
반응형

새로 고침 시 Redux 상태 트리를 유지하려면 어떻게 해야 합니까?

Redux 문서의 첫 번째 원칙은 다음과 같습니다.

전체 응용 프로그램 상태는 단일 저장소 내의 개체 트리에 저장됩니다.

그리고 저는 사실 모든 원리를 잘 이해한다고 생각했어요.그런데 지금 어플리케이션이 무슨 뜻인지 헷갈려요.

앱이 웹사이트의 작은 복잡한 부분 중 하나일 뿐이고, 한 페이지 안에만 작동한다면 이해할 수 있습니다.하지만 어플리케이션이 웹사이트 전체를 의미한다면?상태 트리를 유지하려면 LocalStorage 또는 쿠키 등을 사용해야 합니까?하지만 브라우저가 LocalStorage를 지원하지 않으면 어떻게 됩니까?

개발자가 상태 트리를 어떻게 유지하는지 알고 싶습니다. :)

브라우저 새로 고침 후에도 redux 상태를 유지하려면 redux 미들웨어를 사용하는 것이 가장 좋습니다.Redux-persistRedux-스토리지 미들웨어를 확인하십시오.둘 다 원하는 대로 저장 및 로드할 수 있도록 redex 상태를 저장하는 동일한 작업을 수행하려고 합니다.

--

편집

이 질문을 다시 한 지 꽤 되었지만, 다른 질문(더 높은 답변에도 불구하고)이 독자적으로 해결책을 제시하도록 격려하는 것을 보고, 다시 한 번 대답해야겠다고 생각했습니다.

이 편집 시점에서는 두 라이브러리 모두 지난 6개월 이내에 업데이트되었습니다.저희 팀은 몇 년 전부터 레독스 퍼시스턴트를 생산에 사용하고 있으며 아무런 문제가 없었습니다.

간단한 문제처럼 보일 수도 있지만 자체 솔루션을 도입하면 유지보수의 부담이 가중될 뿐만 아니라 버그와 성능 문제가 발생한다는 것을 금방 알게 될 것입니다.가장 먼저 떠오르는 예는 다음과 같습니다.

  1. JSON.stringify ★★★★★★★★★★★★★★★★★」JSON.parse불필요한 경우 퍼포먼스가 저하될 수 있을 뿐만 아니라 redux 스토어 등의 중요한 코드로 처리하지 않으면 어플리케이션이 크래시 될 수 있습니다.
  2. (아래 답변에서 일부 언급):앱 상태를 저장 및 복원하는 시기와 방법을 파악하는 것은 간단한 문제가 아닙니다.너무 자주 하면 성능이 저하됩니다.충분하지 않거나 잘못된 상태가 지속되면 더 많은 버그가 발생할 수 있습니다.위에서 언급한 라이브러리는 접근법에 대해 전투 테스트를 거쳤으며, 동작을 커스터마이즈할 수 있는 꽤 확실한 방법을 제공합니다.
  3. 리덕스(특히 React 에코시스템)의 장점 중 하나는 여러 환경에 배치할 수 있다는 것입니다.이 편집 시점 현재 redux-persist에는 웹용 localForage 라이브러리와 React Native, Electron 및 Node 지원을 포함하여 15개의 스토리지 구현이 있습니다.

요약하자면, 3kB의 최소 + gzipped(이 편집 시점)에 대해서는 저희 팀에게 직접 해결하도록 요청하고 싶지 않습니다.

2019년 8월 25일 편집

댓글에 써있는 대로.원래 redux 스토리지 패키지가 react-stack으로 이동되었습니다.이 접근법은 여전히 자체 상태 관리 솔루션 구현에 중점을 두고 있습니다.


원답

제공된 답변은 어느 시점에서는 유효하지만, 원래의 redux-storage 패키지가 폐지되어 더 이상 유지보수가 되지 않는다는 점에 유의하십시오.

패키지 redux-storage의 원래 제작자는 프로젝트를 폐지하기로 결정하여 더 이상 유지보수를 하지 않습니다.

향후 이러한 문제를 피하기 위해 다른 패키지에 의존하지 않으려면 자체 솔루션을 구축하는 것이 매우 쉽습니다.

필요한 것은 다음과 같습니다.

1- 상태를 반환하는 함수를 만듭니다.localStorage그 다음 주(州)를 넘기고createStore저장소의 수분을 공급하기 위한 두 번째 파라미터의 sredex 함수

 const store = createStore(appReducers, state);

2-상태변화를듣고상태가변경될 때마다 상태를 저장합니다.localStorage

store.subscribe(() => {
    //this is just a function that saves state to localStorage
    saveState(store.getState());
}); 

그리고 그게 다야...저는 실제로 비슷한 것을 사용하고 있습니다만, 기능을 사용하는 대신 다음과 같이 매우 간단한 수업을 작성했습니다.

class StateLoader {

    loadState() {
        try {
            let serializedState = localStorage.getItem("http://contoso.com:state");

            if (serializedState === null) {
                return this.initializeState();
            }

            return JSON.parse(serializedState);
        }
        catch (err) {
            return this.initializeState();
        }
    }

    saveState(state) {
        try {
            let serializedState = JSON.stringify(state);
            localStorage.setItem("http://contoso.com:state", serializedState);

        }
        catch (err) {
        }
    }

    initializeState() {
        return {
              //state object
            }
        };
    }
}

그 후 앱을 부트스트랩 할 때...

import StateLoader from "./state.loader"

const stateLoader = new StateLoader();

let store = createStore(appReducers, stateLoader.loadState());

store.subscribe(() => {
    stateLoader.saveState(store.getState());
});

도움이 되었으면 좋겠다

퍼포먼스 노트

애플리케이션에서 상태 변경이 매우 빈번한 경우 로컬 스토리지에 너무 자주 저장하면 특히 직렬화/비직렬화할 상태 개체 그래프가 큰 경우 애플리케이션의 성능이 저하될 수 있습니다.이러한 경우 localStorage에 상태를 저장하는 함수를 debounce 또는 throttle로 설정할 수 있습니다.RxJs,lodash뭐 비슷한 거.

이는 Leo의 답변(제3자 립을 사용하지 않고 질문의 목적을 달성하므로 인정된 답변이어야 함)을 기반으로 합니다.

저는 Redux Store를 만들고 로컬 스토리지를 사용하여 유지하며 Getter를 통해 스토어에 쉽게 액세스할있는 Singleton 클래스를 만들었습니다.

이 기능을 사용하려면 메인 클래스 주위에 다음과 같은 Redux-Provider 요소를 배치하십시오.

// ... Your other imports
import PersistedStore from "./PersistedStore";

ReactDOM.render(
  <Provider store={PersistedStore.getDefaultStore().store}>
    <MainClass />
  </Provider>,
  document.getElementById('root')
);

프로젝트에 다음 클래스를 추가합니다.

import {
  createStore
} from "redux";

import rootReducer from './RootReducer'

const LOCAL_STORAGE_NAME = "localData";

class PersistedStore {

  // Singleton property
  static DefaultStore = null;

  // Accessor to the default instance of this class
  static getDefaultStore() {
    if (PersistedStore.DefaultStore === null) {
      PersistedStore.DefaultStore = new PersistedStore();
    }

    return PersistedStore.DefaultStore;
  }

  // Redux store
  _store = null;

  // When class instance is used, initialize the store
  constructor() {
    this.initStore()
  }

  // Initialization of Redux Store
  initStore() {
    this._store = createStore(rootReducer, PersistedStore.loadState());
    this._store.subscribe(() => {
      PersistedStore.saveState(this._store.getState());
    });
  }

  // Getter to access the Redux store
  get store() {
    return this._store;
  }

  // Loading persisted state from localStorage, no need to access
  // this method from the outside
  static loadState() {
    try {
      let serializedState = localStorage.getItem(LOCAL_STORAGE_NAME);

      if (serializedState === null) {
        return PersistedStore.initialState();
      }

      return JSON.parse(serializedState);
    } catch (err) {
      return PersistedStore.initialState();
    }
  }

  // Saving persisted state to localStorage every time something
  // changes in the Redux Store (This happens because of the subscribe() 
  // in the initStore-method). No need to access this method from the outside
  static saveState(state) {
    try {
      let serializedState = JSON.stringify(state);
      localStorage.setItem(LOCAL_STORAGE_NAME, serializedState);
    } catch (err) {}
  }

  // Return whatever you want your initial state to be
  static initialState() {
    return {};
  }
}

export default PersistedStore;

언급URL : https://stackoverflow.com/questions/37195590/how-can-i-persist-redux-state-tree-on-refresh

반응형