কোনও রেডাক্স অ্যাপে লোকালস্টোরারে কোথায় লিখবেন?


166

আমি আমার রাজ্য গাছের কিছু অংশ লোকাল স্টোরেজে চালিয়ে যেতে চাই। এটি করার উপযুক্ত জায়গাটি কী? রিডুসার বা অ্যাকশন?

উত্তর:


223

রিডিউসার এটি করার জন্য কখনই উপযুক্ত জায়গা নয় কারণ হ্রাসকারীদের খাঁটি হওয়া উচিত এবং এর কোনও পার্শ্ব প্রতিক্রিয়া নেই।

আমি এটি কেবল গ্রাহক হয়ে করার পরামর্শ দিচ্ছি:

store.subscribe(() => {
  // persist your state
})

স্টোর তৈরি করার আগে, এই অবিরাম অংশগুলি পড়ুন:

const persistedState = // ...
const store = createStore(reducer, persistedState)

আপনি যদি ব্যবহার করেন তবে combineReducers()খেয়াল করবেন যে রাজ্যটি প্রাপ্তি হ্রাসকারীরা তাদের ডিফল্ট stateআর্গুমেন্ট মানটি স্বাভাবিক হিসাবে "বুট আপ" করবে । এটি বেশ সহজ হতে পারে।

আপনি আপনার গ্রাহককে ডাবনো করা বাঞ্ছনীয় তাই আপনি লোকালস্টোরারে খুব দ্রুত লিখবেন না, বা আপনার পারফরম্যান্সে সমস্যা হবে।

অবশেষে, আপনি একটি মিডলওয়্যার তৈরি করতে পারেন যা বিকল্প হিসাবে এটি encapsulates, তবে আমি একটি গ্রাহক দিয়ে শুরু করব কারণ এটি একটি সহজ সমাধান এবং কাজটি ভালভাবে করে।


1
আমি যদি রাজ্যের কেবলমাত্র অংশে সাবস্ক্রাইব করতে চাই? এটা কি সম্ভব? আমি কিছুটা আলাদা কিছু নিয়ে এগিয়ে গেলাম: ১. রিডেক্সের বাইরে অবিচ্ছিন্ন রাজ্যটি সংরক্ষণ করুন। ২. রিডাক্স অ্যাকশনের মাধ্যমে রিঅ্যাক্ট কনস্ট্রাক্টরের (বা উপাদানওয়ালমাউন্ট সহ) স্থিতিস্থাপক অবস্থা লোড করুন। 2 স্টোরের উপর স্থির থাকা ডেটা সরাসরি লোড করার পরিবর্তে 2 কি পুরোপুরি ঠিক আছে? (যা আমি এসএসআরের জন্য আলাদা রাখার চেষ্টা করছি)। উপায় দ্বারা Redux জন্য ধন্যবাদ! এটা দুর্দান্ত, আমি এটি ভালবাসি, আমার বড় প্রজেক্ট কোডটি হারিয়ে যাওয়ার পরে এখন এটি সহজ এবং অনুমানযোগ্য :)
মার্ক ইউরেটস্কি

স্টোর সাবস্ক্রাইব কলব্যাকের মধ্যে, আপনার বর্তমান স্টোরের ডেটাতে সম্পূর্ণ অ্যাক্সেস রয়েছে, যাতে আপনি আগ্রহী যে কোনও অংশটি চালিয়ে যেতে পারেন
বো চেন

35
: ড্যান Abramov এছাড়াও এটি একটি সমগ্র ভিডিওটি করেছেন egghead.io/lessons/...
NateW

2
প্রতি স্টোর আপডেটে রাজ্যকে সিরিয়ালকরণের সাথে বৈধ কর্মক্ষমতা সম্পর্কিত উদ্বেগ রয়েছে? ব্রাউজারটি কি আলাদা থ্রেডে সিরিয়ালাইজ হতে পারে?
স্টিফেন পল

7
এটি সম্ভাব্য অপব্যয় দেখাচ্ছে। ওপি বলেছিল যে রাজ্যের কেবলমাত্র একটি অংশই বহাল থাকবে। ধরা যাক আপনার কাছে 100 টি আলাদা কী রয়েছে have আপনি কেবল তাদের মধ্যে 3 টিরই অবিচ্ছিন্নভাবে পরিবর্তন করতে চান যা প্রায়শই পরিবর্তিত হয়। এখন আপনি আপনার 100 টির যে কোনওতে প্রতিটি সামান্য পরিবর্তনে স্থানীয় স্টোরটিকে পার্সিং এবং আপডেট করছেন, আপনি যখন স্থায়ী হতে আগ্রহী 3 টি কী কোনওরও পরিবর্তন করা যায় নি। নীচে @ গার্ডিজির সমাধান আরও ভাল পদ্ধতির কারণ আপনি ইভেন্ট শ্রোতাদের আপনার মিডলওয়্যারের সাথে যুক্ত করতে পারেন যাতে আপনি কেবল তখন আপডেট হন যখন আপনার আসলে প্রয়োজন যেমন: কোডেপেন.আইও
আনা টি

153

ড্যান আব্রামভের উত্তরের শূন্যস্থান পূরণ করতে আপনি এটি ব্যবহার করতে পারেন store.subscribe():

store.subscribe(()=>{
  localStorage.setItem('reduxState', JSON.stringify(store.getState()))
})

স্টোরটি তৈরি করার আগে localStorageআপনার কী এর অধীনে কোনও জেএসএনকে পরীক্ষা করে পার্স করুন:

const persistedState = localStorage.getItem('reduxState') 
                       ? JSON.parse(localStorage.getItem('reduxState'))
                       : {}

তারপরে আপনি এই persistedStateধ্রুবকটি আপনার createStoreপদ্ধতিতে এভাবে পাস করুন :

const store = createStore(
  reducer, 
  persistedState,
  /* any middleware... */
)

6
অতিরিক্ত নির্ভরতা ছাড়াই সহজ এবং কার্যকর।
এক্সেএফেক্ট

1
মিডলওয়্যার তৈরি করা কিছুটা ভাল দেখায়, তবে আমি সম্মত হই যে এটি কার্যকর এবং বেশিরভাগ ক্ষেত্রেই যথেষ্ট
বো চেন

কম্বাইনারিডুসারদের ব্যবহার করার জন্য কি এখানে করার কোনও দুর্দান্ত উপায় আছে এবং আপনি কেবল একটি দোকান চালিয়ে যেতে চান?
brendangibson

1
লোকালস্টোরারে কিছুই যদি না থাকে তবে খালি বস্তুর পরিবর্তে persistedStateফিরে আসা উচিত initialState? অন্যথায় আমি মনে করি createStoreযে শূন্য বস্তুটি দিয়ে আরম্ভ করব।
অ্যালেক্স

1
অ্যালেক্স আপনি ঠিক বলেছেন, যদি না আপনার প্রাথমিক স্টেটটি খালি থাকে।
লিংক 14

47

এক কথায়: মিডওয়্যার

Redx-persist দেখুন । বা আপনার নিজের লিখুন।

[আপডেট 18 ডিসেম্বর 2016] একই রকম দুটি প্রকল্পের নিষ্ক্রিয়করণ বা নিষ্ক্রিয় করা এখন সরানোর জন্য সম্পাদিত।


12

উপরের সমাধানগুলি নিয়ে কারও যদি সমস্যা হয়, আপনি নিজের লিখতে পারেন। আমি কি করেছি তা আপনাকে দেখাতে দিন। 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;

2
হাই, localStorageস্টোরের কোনও কিছুই পরিবর্তিত না হয়েও কী এই লেখার প্রচুর ফলাফল হবে না ? অপ্রয়োজনীয় লেখার জন্য আপনি কীভাবে ক্ষতিপূরণ করবেন
ব্যবহারকারীর 576245

ওয়েল, এটি কাজ করে, যাইহোক এটি এই ভাল ধারণা থাকা উচিত? প্রশ্ন: বড় ডেটা সহ একাধিক হ্রাসকারী আমাদের আরও ডেটা মেনাসের ক্ষেত্রে কী ঘটবে?
কুনভার সিং

3

আমি @ গ্রাডিজিকে উত্তর দিতে পারি না তবে তার কোডের ভিত্তিতে একটি বিকল্প হতে পারে:

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
    )
);

পার্থক্যটি হ'ল আমরা কেবল কিছু ক্রিয়াকলাপ সংরক্ষণ করছি, আপনি কেবলমাত্র আপনার রাজ্যের শেষ ইন্টারঅ্যাকশনটি সংরক্ষণ করতে কোনও ডেবিউন ফাংশন ব্যবহার করতে পারেন event


1

আমি কিছুটা দেরি করেছি তবে আমি এখানে বর্ণিত উদাহরণ অনুসারে একটি অবিরাম রাষ্ট্র বাস্তবায়ন করেছি। আপনি যদি প্রতি এক্স সেকেন্ডের মধ্যে রাষ্ট্রটি আপডেট করতে চান তবে এই পদ্ধতি আপনাকে সহায়তা করতে পারে:

  1. একটি মোড়ক ফাংশন সংজ্ঞায়িত করুন

    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!")
        }
    }
  2. আপনার গ্রাহকের একটি মোড়ক ফাংশন কল করুন

        store.subscribe((state) =>
        {
        updateLocalStorage(store.getState())
         });

এই উদাহরণে, রাষ্ট্র আপডেট করা হয় সর্বাধিক প্রতিটি 5 সেকেন্ড নির্বিশেষে কত ঘন ঘন একটি আপডেট সূত্রপাত হয়।


1
আপনি মোড়ানো পারে (state) => { updateLocalStorage(store.getState()) }মধ্যে lodash.throttleভালো: store.subscribe(throttle(() => {(state) => { updateLocalStorage(store.getState())} }এবং যুক্তিবিদ্যা ভিতরে পরীক্ষণ সময় মুছে ফেলুন।
জর্জএমএ

1

অন্যান্য উত্তরগুলিতে (এবং জাম ক্রিনিসিয়ার মাঝারি নিবন্ধ ) সরবরাহিত দুর্দান্ত পরামর্শ এবং সংক্ষিপ্ত কোডের অংশগুলির উপর ভিত্তি করে এখানে একটি সম্পূর্ণ সমাধান!

আমাদের দুটি ফাংশন সমন্বিত একটি ফাইল দরকার যা স্থানীয় সঞ্চয়স্থানে / থেকে রাষ্ট্রটিকে / সঞ্চয় করে:

// 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')
)

নোট করুন যে নিখুঁত আমদানিগুলির জন্য আপনার প্রজেক্টফোল্ডার / jsconfig.json- এ এই পরিবর্তন দরকার - এটি প্রথমে যদি ফাইলগুলি না খুঁজে পায় তবে এটি কোথায় সন্ধান করতে হবে তা এটি বলে। অন্যথায়, আপনি এসআরসি-র বাইরে থেকে কিছু আমদানির চেষ্টা করার বিষয়ে অভিযোগগুলি দেখতে পাবেন ।

{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "include": ["src"]
}

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.