Categories
Programming React User Interface

React – UseLocationState hook

This hook, made in typescript, can be used to change the current location state. Just use it as you would use the useState hook.

import { useHistory } from "react-router-dom";
import { useCallback } from "react";

//callback definition.
type SetStateType<T> = ((prevState: T) => T) | T;

export default <T extends any>(defaultState: T)
    : [T, (newState: SetStateType<T>) => void] => {

    const { replace, location: { state } } = useHistory<T>(); 
    const currentState = isNullOrUndefined(state) ? defaultState : state;

    const setState = useCallback((newState: SetStateType<T>) => {
        const state = (newState instanceof Function)
            ? newState(currentState)
            : newState;
        state !== currentState && replace({ state });
    }, [replace, currentState]);

 return [currentState, setState];
}

UPDATE Jan 2022: Simplified version using useState():

import { useHistory } from "react-router-dom";
import { useEffect, useState } from "react";

//callback definition.
type SetStateType<T> = ((prevState: T) => T) | T;

const useLocationState = <T extends any>(defaultState: T)
    : [T, (newState: SetStateType<T>) => void] => {

    const { replace, location } = useHistory<T>();
    const [state, setState] = useState<T>(location.state || defaultState);

    //save state in locationState
    useEffect(() => {
        location.state !== state && replace({ state });        
    }, [replace, state, location.state])

    return [state, setState];
}

export default useLocationState;

Example:

import * as React from 'react';
import useLocationState from '../UseLocationState';

export default (() => {
    const [someState, setSomeState] = useLocationState({ test: 1 });

    //change location state (2 options)
    useEffect(() => {
        //option 1
        setSomeState({ test: 10 });
        //option 2
        setSomeState(prev => ({ test: prev.test - 5 })) ;
    }, [setSomeState]);

    return <>{someState}</>
}

Categories
User Interface

React Prompt on page unload (Typescript)

This React Prompt Component allows you to show a dialog before closing a page or when navigating to another page. This is an extension on the existing prompt component within React which only shows dialog messages when navigating with React Router. This component works in hooks and class components.

Copy paste the code below and save it as DirtyPrompt.tsx