Redux 앱에서 localStorage에 쓸 수 있는 위치
상태 트리의 일부를 localStorage에 유지하려고 합니다.그렇게 하기 위한 적절한 장소는 어디입니까?리듀서? 액션?
환원제는 순수해야 하고 부작용이 없어야 하기 때문에 환원제는 결코 이것을 하기에 적절한 장소가 아닙니다.
서브스크라이버 내에서만 실행할 것을 권장합니다.
store.subscribe(() => {
// persist your state
})
스토어를 작성하기 전에, 다음의 영속적인 부분을 읽어 주세요.
const persistedState = // ...
const store = createStore(reducer, persistedState)
「 」를 사용하고 combineReducers()
인 「 업state
은 매우할 수 있습니다.을 사용하다
localStorage에 너무 빨리 쓰지 않도록 가입자를 선언하는 것이 좋습니다. 그렇지 않으면 성능 문제가 발생합니다.
마지막으로 이를 캡슐화하는 미들웨어를 만들 수 있지만, 우선 서브스크라이버부터 설명하겠습니다.그것은 보다 심플한 솔루션이며, 작업을 잘 하기 때문입니다.
댄 아브라모프의 대답 빈칸을 채우려면store.subscribe()
음음음같 뭇매하다
store.subscribe(()=>{
localStorage.setItem('reduxState', JSON.stringify(store.getState()))
})
에 체크박스를 .localStorage
JSON을 같이 분석합니다.
const persistedState = localStorage.getItem('reduxState')
? JSON.parse(localStorage.getItem('reduxState'))
: {}
후, 이 「」를 합니다.persistedState
createStore
하다
const store = createStore(
reducer,
persistedState,
/* any middleware... */
)
한마디로 미들웨어.
redex-persist 를 확인해 주세요.아니면 직접 쓰거나.
[UPDATE 2016년 12월 18일]비활성화 또는 폐지된 두 개의 유사한 프로젝트에 대한 언급을 삭제하도록 편집되었습니다.
위의 해결책에 대해 문제가 있는 사용자는 다음 주소로 직접 글을 쓸 수 있습니다.내가 뭘 했는지 보여줄게.ignore ★saga middleware
의 은 딱 두 localStorageMiddleware
★★★★★★★★★★★★★★★★★」reHydrateStore
법 the. the ★localStorageMiddleware
수단을 다 쓰다redux state
그것을 어요에 넣습니다.local storage
★★★★★★★★★★★★★★★★★」rehydrateStore
수단을 다 쓰다applicationState
로컬 스토리지(존재하는 경우)에 저장하여 저장합니다.redux store
import {createStore, applyMiddleware} from 'redux'
import createSagaMiddleware from 'redux-saga';
import decoristReducers from '../reducers/decorist_reducer'
import sagas from '../sagas/sagas';
const sagaMiddleware = createSagaMiddleware();
/**
* Add all the state in local storage
* @param getState
* @returns {function(*): function(*=)}
*/
const localStorageMiddleware = ({getState}) => { // <--- FOCUS HERE
return (next) => (action) => {
const result = next(action);
localStorage.setItem('applicationState', JSON.stringify(
getState()
));
return result;
};
};
const reHydrateStore = () => { // <-- FOCUS HERE
if (localStorage.getItem('applicationState') !== null) {
return JSON.parse(localStorage.getItem('applicationState')) // re-hydrate the store
}
}
const store = createStore(
decoristReducers,
reHydrateStore(),// <-- FOCUS HERE
applyMiddleware(
sagaMiddleware,
localStorageMiddleware,// <-- FOCUS HERE
)
)
sagaMiddleware.run(sagas);
export default store;
다른 답변(Jam Creencia의 Medium 기사)에서 제공되는 뛰어난 제안과 짧은 코드 발췌를 바탕으로 완벽한 솔루션을 소개합니다.
로컬 스토리지에서 상태를 저장/로드하는 두 가지 기능이 포함된 파일이 필요합니다.
// FILE: src/common/localStorage/localStorage.js
// Pass in Redux store's state to save it to the user's browser local storage
export const saveState = (state) =>
{
try
{
const serializedState = JSON.stringify(state);
localStorage.setItem('state', serializedState);
}
catch
{
// We'll just ignore write errors
}
};
// Loads the state and returns an object that can be provided as the
// preloadedState parameter of store.js's call to configureStore
export const loadState = () =>
{
try
{
const serializedState = localStorage.getItem('state');
if (serializedState === null)
{
return undefined;
}
return JSON.parse(serializedState);
}
catch (error)
{
return undefined;
}
};
이러한 함수는 스토어를 구성하는 store.js에 의해 Import됩니다.
메모: 종속성을 하나 추가해야 합니다.
// FILE: src/app/redux/store.js
import { configureStore, applyMiddleware } from '@reduxjs/toolkit'
import throttle from 'lodash.throttle';
import rootReducer from "./rootReducer";
import middleware from './middleware';
import { saveState, loadState } from 'common/localStorage/localStorage';
// By providing a preloaded state (loaded from local storage), we can persist
// the state across the user's visits to the web app.
//
// READ: https://redux.js.org/recipes/configuring-your-store
const store = configureStore({
reducer: rootReducer,
middleware: middleware,
enhancer: applyMiddleware(...middleware),
preloadedState: loadState()
})
// We'll subscribe to state changes, saving the store's state to the browser's
// local storage. We'll throttle this to prevent excessive work.
store.subscribe(
throttle( () => saveState(store.getState()), 1000)
);
export default store;
저장소는 index.js로 Import되므로 App.js를 랩하는 프로바이더로 전달됩니다.
// FILE: src/index.js
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import App from './app/core/App'
import store from './app/redux/store';
// Provider makes the Redux store available to any nested components
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
절대 Import에서는 YourProjectFolder/jsconfig.json으로 변경해야 합니다.처음에는 파일을 찾을 수 없는 경우 파일을 찾을 수 있는 위치가 표시됩니다.그렇지 않으면 src 외부에서 Import를 시도한다는 불만이 표시됩니다.
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
@Gardezi에는 대답할 수 없지만, 그의 코드에 근거한 옵션은 다음과 같습니다.
const rootReducer = combineReducers({
users: authReducer,
});
const localStorageMiddleware = ({ getState }) => {
return next => action => {
const result = next(action);
if ([ ACTIONS.LOGIN ].includes(result.type)) {
localStorage.setItem(appConstants.APP_STATE, JSON.stringify(getState()))
}
return result;
};
};
const reHydrateStore = () => {
const data = localStorage.getItem(appConstants.APP_STATE);
if (data) {
return JSON.parse(data);
}
return undefined;
};
return createStore(
rootReducer,
reHydrateStore(),
applyMiddleware(
thunk,
localStorageMiddleware
)
);
차이점은 우리는 단지 몇 가지 액션을 저장했을 뿐이라는 것입니다.이벤트는 debounce 함수를 사용하여 상태의 마지막 상호작용만 저장할 수 있습니다.
조금 늦었지만 여기에 나와 있는 예에 따라 끈질긴 상태를 구현했습니다.상태를 X초마다만 갱신하는 경우, 이 방법을 사용하면 다음과 같은 이점이 있습니다.
래퍼 함수를 정의합니다.
let oldTimeStamp = (Date.now()).valueOf() const millisecondsBetween = 5000 // Each X milliseconds function updateLocalStorage(newState) { if(((Date.now()).valueOf() - oldTimeStamp) > millisecondsBetween) { saveStateToLocalStorage(newState) oldTimeStamp = (Date.now()).valueOf() console.log("Updated!") } }
가입자의 래퍼 함수를 호출합니다.
store.subscribe((state) => { updateLocalStorage(store.getState()) });
이 예에서는 업데이트가 트리거되는 빈도에 관계없이 최대 5초마다 상태가 업데이트됩니다.
모든 redex 저장소를 localStorage에 복사할 필요가 없는 경우 특정 store 인수를 사용할 수 있습니다.
store.subscribe(()=>{
window.localStorage.setItem('currency', store.getState().lang)
})
또한 다음과 같이 초기 상태 인수 값을 설정합니다.
const initialState = {
currency: window.localStorage.getItem('lang') ?? 'en',
}
이 경우 합격할 필요가 없습니다.const persistedState
로.const store = createStore()
redux-toolkit-persist를 사용하여 로컬 스토리지에 상태를 유지하는 방법에 대한 전체 예를 찾았지만 성공하지 못했습니다. 위의 @canPro 응답을 통해 문제를 해결했습니다.이것이 나에게 효과가 있는 것이다.
//package.json
"reduxjs-toolkit-persist": "^7.0.1",
"lodash": "^4.17.21"
//localstorage.ts
import localStorage from 'reduxjs-toolkit-persist/es/storage';
export const saveState = (state: any) => {
try {
console.log(state);
const serializableState = JSON.stringify(state);
localStorage.setItem('globalState', serializableState);
} catch (err) {
console.log('Redux was not able to persist the state into the localstorage');
}
};
export const loadState = () => {
try {
const serializableState: string | any =
localStorage.getItem('globalState');
return serializableState !== null || serializableState === undefined ? JSON.parse(serializableState) : undefined;
} catch (error) {
return undefined;
}
};
//slices - actions
//reduxjs-toolkit-slices.ts
import { combineReducers, createSlice, PayloadAction } from '@reduxjs/toolkit';
import { UserModel } from '../model/usermodel';
import { GlobalState } from './type';
const deaultState: GlobalState = {
counter: 0,
isLoggedIn: false
};
const stateSlice = createSlice({
name: "state",
initialState: deaultState,
reducers: {
isLoggedIn: (state, action: PayloadAction<boolean>) => {
console.log('isLogged');
console.log(state.isLoggedIn);
console.log(action);
state.isLoggedIn = action.payload;
console.log(state.isLoggedIn);
},
setUserDetails: (state, action: PayloadAction<UserModel>) => {
console.log('setUserDetails');
console.log(state);
console.log(action);
//state.userContext.user = action.payload;
}
}
});
//export actions under slices
export const {
isLoggedIn: isUserLoggedAction,
setUserDetails: setUserDetailActions
} = stateSlice.actions;
//TODO: use the optimal way for combining reducer using const
//combine reducer from all slice
export const combineReducer = combineReducers({
stateReducer: stateSlice.reducer
});
//storeConfig
//reduxjs-toolkit-store.ts
import { configureStore } from '@reduxjs/toolkit';
import { throttle } from 'lodash';
import { persistReducer } from 'reduxjs-toolkit-persist';
import autoMergeLevel2 from 'reduxjs-toolkit-persist/lib/stateReconciler/autoMergeLevel2';
import storage from 'reduxjs-toolkit-persist/lib/storage';
import { loadState, saveState } from './localStorage';
import { combineReducer } from './reduxjs-toolkit-slices';
// persist config
const persistConfig = {
key: 'root',
storage: storage,
stateReconciler: autoMergeLevel2,
};
const persistedReducer = persistReducer(persistConfig, combineReducer);
// export reducers under slices
const store = configureStore({
reducer: persistedReducer,
devTools: process.env.NODE_ENV !== 'production',
preloadedState: loadState(), //call loadstate method to initiate store from localstorage
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
thunk: true,
serializableCheck: false,
}),
});
// handle state update event. Whenever the state will change, this subscriber will call the saveState methode to update and persist the state into the store
store.subscribe(throttle(() => {
saveState(store.getState());
}, 1000));
export default store;
//App.ts
import { persistStore } from 'reduxjs-toolkit-persist';
import { PersistGate } from 'reduxjs-toolkit-persist/integration/react';
import './i18n';
let persistor = persistStore(store);
ReactDOM.render(
<Provider store={store}>
<PersistGate loading={<div>Loading .....</div>} persistor={persistor}>
<HalocarburesRouter />
</PersistGate>
</Provider>,
document.getElementById('ingenierieMdn'));
언급URL : https://stackoverflow.com/questions/35305661/where-to-write-to-localstorage-in-a-redux-app
'programing' 카테고리의 다른 글
MySQL에서 "오버헤드"는 무엇을 의미하며, 무엇이 문제이며, 어떻게 수정해야 합니까? (0) | 2023.01.31 |
---|---|
Android: export를 명시적으로 지정해야 합니다. Android 12 이상을 대상으로 하는 앱은 다음을 지정해야 합니다. (0) | 2023.01.31 |
unix_timestamp(MySQL)의 데이터 유형은 무엇입니까? (0) | 2023.01.21 |
javascript에서 숫자를 반올림하는 방법은 무엇입니까? (0) | 2023.01.21 |
장고 구글 앱 엔진 서버 오류 500 (0) | 2023.01.21 |