You can create a Route Context
to handle the routes changes and create listeners for those components where you need to save the data before changing the route or prevent the route changes:
RouteProvider.js
Add this component to the top of your component structure, but inside the Router
component.
const RouteContext = React.createContext();
const RouteProvider = ({ children }) => {
const locationKey = useRef({ /* keep tracking the route history */
to: null,
from: null,
});
const listeners = useRef({});
const history = useHistory();
useEffect(() => {
/* set the locationKey value during the first render*/
locationKey.current = {
from: history.location.pathname,
to: history.location.pathname
}
return history.block(({ pathname }, action) => {
if(locationKey.current.to === pathname) return;
if (locationKey.current.from === pathname) {
/** you are going to the last route visited */
const listenerValues = Object.values(listeners.current);
listenerValues.forEach(({callback, prevent}) => {
callback();
});
/** if one listener needs to prevent the route changes */
if(listenerValues.find(({prevent})=> prevent)) return false;
}
locationKey.current = { from: locationKey.current.to, to: pathname };
});
}, [history]);
/* add listeners*/
const onBackListener = (callback, prevent = false) => {
const ID = Date.now;
listeners.current[ID] = {
callback,
prevent,
};
return ID;
};
/* remove listeners*/
const removeListener = (ID) => delete listeners.current[ID] ;
return <RouteContext.Provider value={{onBackListener, removeListener}}>{children}</RouteContext.Provider>;
};
SecondComponent.js
This component will add a listener to the RouteContext and will prevent the route changes.
function Second() {
const {onBackListener, removeListener} = React.useContext(RouteContext);
const [state, setState] = useState();
useEffect(()=> {
const listener = onBackListener(()=> {
/**save data */
console.log("saving data");
setState("Data")
}, true);
return () => removeListener(listener);
}, []);
return <h2>Second Page</h2>;
}
I didn't test all possibles escenarios but it will give you an idea of how to transform this to accomplish your requirements.
Working example If you try to go from Second component to the Home component the data is saved and the route doesn't changes.