मैं अपने स्टेट ट्री के कुछ हिस्सों को लोकलस्टोरेज पर कायम रखना चाहता हूं। ऐसा करने के लिए उपयुक्त स्थान क्या है? Reducer या कार्रवाई?
मैं अपने स्टेट ट्री के कुछ हिस्सों को लोकलस्टोरेज पर कायम रखना चाहता हूं। ऐसा करने के लिए उपयुक्त स्थान क्या है? Reducer या कार्रवाई?
जवाबों:
Reducer ऐसा करने के लिए एक उपयुक्त स्थान नहीं है क्योंकि Reducers शुद्ध होने चाहिए और कोई साइड इफेक्ट नहीं होना चाहिए।
मैं इसे एक ग्राहक में करने की सलाह दूंगा:
store.subscribe(() => {
// persist your state
})
स्टोर बनाने से पहले, उन भागों को पढ़ें:
const persistedState = // ...
const store = createStore(reducer, persistedState)
यदि आप उपयोग करते हैं, combineReducers()
तो आप देखेंगे कि राज्य को प्राप्त नहीं हुए रिड्यूसर अपने डिफ़ॉल्ट state
तर्क मान का उपयोग करके सामान्य रूप से "बूट" करेंगे । यह बहुत आसान हो सकता है।
यह सलाह दी जाती है कि आप अपने सब्सक्राइबर की आलोचना करें ताकि आप लोकलस्टोरेज को बहुत तेजी से न लिखें, या आपको प्रदर्शन की समस्या हो।
अंत में, आप एक मिडलवेयर बना सकते हैं जो एक विकल्प के रूप में एनकैप्सुलेट करता है, लेकिन मैं एक सब्सक्राइबर के साथ शुरू करूंगा क्योंकि यह एक सरल समाधान है और यह अच्छी तरह से काम करता है।
दान Abramov के जवाब के रिक्त स्थान को भरने के लिए आप 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... */
)
persistedState
वापस लौटना चाहिए initialState
? अन्यथा मुझे लगता है createStore
कि उस खाली वस्तु के साथ आरंभ होगा।
एक शब्द में: मिडलवेयर।
Redux-persist की जाँच करें । या अपना खुद का लिखो।
[अद्यतन १ UP दिसंबर २०१६] दो समान परियोजनाओं के उल्लेख को हटाने के लिए संपादित अब निष्क्रिय या पदावनत।
यदि किसी को उपरोक्त समाधानों से कोई समस्या हो रही है, तो आप अपना स्वयं का लिख सकते हैं। मैं तुम्हें दिखाता हूं कि मैंने क्या किया। saga middleware
चीजों को नजरअंदाज करें बस दो चीजों localStorageMiddleware
और reHydrateStore
विधि पर ध्यान दें । 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;
localStorage
जब तक दुकान में कुछ भी नहीं बदला है तब भी यह बहुत कुछ नहीं लिखता है ? आप अनावश्यक लेखन के लिए क्षतिपूर्ति कैसे करते हैं
मैं @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
)
);
अंतर यह है कि हम केवल कुछ कार्यों को सहेज रहे हैं, आप अपने राज्य के केवल अंतिम इंटरैक्शन को बचाने के लिए एक डेबिट फ़ंक्शन का उपयोग कर सकते हैं
मुझे थोड़ी देर हो गई है लेकिन मैंने यहां बताए गए उदाहरणों के अनुसार एक स्थिर स्थिति को लागू किया है। यदि आप केवल हर 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 सेकंड में अपडेट किया जाता है, भले ही कोई अपडेट कितनी बार चालू हो।
(state) => { updateLocalStorage(store.getState()) }
में lodash.throttle
इस तरह: store.subscribe(throttle(() => {(state) => { updateLocalStorage(store.getState())} }
और तर्क के अंदर की जाँच के समय को हटा दें।
अन्य सुझावों (और जाम क्रेन्सिया के मध्यम लेख ) में प्रदान किए गए उत्कृष्ट सुझावों और लघु कोड अंशों का निर्माण , यहाँ एक पूर्ण समाधान है!
हमें एक फ़ाइल की आवश्यकता है जिसमें 2 कार्य हों जो स्थानीय भंडारण से / को राज्य को बचाते / लोड करते हैं:
// 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 द्वारा आयात किया जाता है जहां हम अपने स्टोर को कॉन्फ़िगर करते हैं:
नोट: आपको एक निर्भरता जोड़ने की आवश्यकता होगी: npm install lodash.throttle
// 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 में आयात किया जाता है, इसलिए इसे प्रदाता में पास किया जा सकता है जो 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')
)
ध्यान दें कि संपूर्ण आयात को YourProjectFolder / jsconfig.json में इस बदलाव की आवश्यकता होती है - यह इसे बताता है कि फ़ाइलों को कहाँ देखना है अगर यह उन्हें पहले नहीं मिल सकता है। अन्यथा, आपको src के बाहर से कुछ आयात करने के प्रयास के बारे में शिकायतें दिखाई देंगी ।
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}