Darren
Darren

Reputation: 2290

Remembering state in react through refreshes

I am looking for a solution that will store state locally when refreshing the browser.

Our app has many translations with a language selector but currently upon a browser refresh this state is reset to the default.

Within the app, as authorised we save the chosen language to Firebase and onMount the chosen user language is shown, however, on our page without authentication, such as the login page and create page, this is not possible.

Currently, language is selected and stored as a state using Context as

import React, { useReducer } from 'react';

// Translations
import EN from '../../../constants/translations/en.json';
import TR from '../../../constants/translations/tr.json';
import ES from '../../../constants/translations/es.json';

interface InterfaceState {
  langCode?: string;
  translate?: any;
  dispatch: any;
}

const translations: any = {
  en: EN,
  tr: TR,
  es: ES
};

const getTranslate = (langCode: string) => (key: string | number) =>
  translations[langCode][key] || key;

const initialState = {
  langCode: 'en',
  translate: getTranslate('en'),
  dispatch: ''
};

export const I18nContext = React.createContext<InterfaceState>(initialState);

export const I18nContextProvider = ({ children }: any) => {
  const reducer = (state: any, action: { type: any; payload: any }) => {
    switch (action.type) {
      case 'setLanguage':
        return {
          langCode: action.payload,
          translate: getTranslate(action.payload)
        };
      default:
        return { ...initialState };
    }
  };

  const [state, dispatch] = useReducer(reducer, initialState);
  const value = { ...state, dispatch };

  return <I18nContext.Provider value={value as any}>{children}</I18nContext.Provider>;
};

The language selector uses useContext to set state and this works fine until the user refreshes the browser and the default langCode is applied.

One solution I've tried that works but has required much to keep maintained, especially as it requires me to add additional steps to Link components, is to history.push(pathname) and add a string query with the langCode in a string as

const onLanguageSelect = (data: any) => {
  dispatch({ type: 'setLanguage', payload: data.value });
  history.push(location.pathname + `?lang=` + data.value);
};

My question, how can I store the chosen state to session or local storage? And is this a viable and scalable solution, especially across multiple domains as app.example.com and example.com?

Upvotes: 1

Views: 76

Answers (2)

Dominik Matis
Dominik Matis

Reputation: 2146

You can use iframe to share what you have saved in localStorage/sessionStorage

Here is the link

Upvotes: 1

Raoul
Raoul

Reputation: 321

Good question. I think local or session is not the option. As it is not saved across different subdomains. I think an option might be to use a cookie. Cookies can be shared with multiple sub domains without a problem.

Just save it in a cookie when you language is selected and fetch in in the default value of your context if it is defined.

Only downside is that some people have set their cookies off by default. So you might need to add a prompt that suggests the user to turn on their cookies for you application.

Upvotes: 0

Related Questions