Blog>
Snippets

Integrating Navigation Blocking with State Management

Provide an example of integrating navigation blocking logic with a global state management solution (e.g., Redux or Context API), to block navigation based on application state.
import { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Prompt } from 'react-router-dom';
Imports necessary hooks from react, react-redux for state management, and Prompt from react-router-dom for navigation blocking.
const NavigationBlocker = () => {
  const dispatch = useDispatch();
  const shouldBlockNavigation = useSelector(state => state.ui.shouldBlockNavigation);

  useEffect(() => {
    // Potentially setup event listeners or dispatch actions based on the component lifecycle
  }, [dispatch]);

  return (
    <Prompt
      when={shouldBlockNavigation}
      message='Are you sure you want to leave this page? Changes you made may not be saved.'
    />
  );
};
Defines a component that uses the Prompt component from react-router-dom to conditionally block navigation based on the shouldBlockNavigation flag from the global state.
// In your store setup file
import { createStore } from 'redux';

// Define the initial state
const initialState = {
  ui: {
    shouldBlockNavigation: false
  }
};

// Define a reducer
const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'SET_NAVIGATION_BLOCK':
      return {
        ...state,
        ui: { ...state.ui, shouldBlockNavigation: action.payload }
      };
    default:
      return state;
  }
};

// Create the store
const store = createStore(rootReducer);
Sets up a Redux store with a simple reducer and action for updating the shouldBlockNavigation state.
// Action Creator
const setNavigationBlock = (shouldBlock) => ({
  type: 'SET_NAVIGATION_BLOCK',
  payload: shouldBlock
});
Defines an action creator for updating the shouldBlockNavigation flag in the global state.
// Usage example inside another component
const ComponentWithForm = () => {
  const dispatch = useDispatch();

  const handleFormChange = () => {
    // Logic to determine if navigation should be blocked
    dispatch(setNavigationBlock(true));
  };

  return (
    <form onChange={handleFormChange}>
      {/* Form Fields Here */}
    </form>
  );
};
Example usage in a Form component, where navigation should be blocked if there are unsaved changes. Dispatches the action to update shouldBlockNavigation on form changes.