How I built a simple react-navigation clone in 5 minutes

How I built a simple react-navigation clone in 5 minutes

React navigation is a really powerful library. But you often don't need that much.

Building your library for this case teaches you a lot about React Context API and how simple the navigation in a SPA happens.

Integration

export function App() {
  return (
    <NavProvider>
      <Router></Router>
    </NavProvider>
  );
}

Defining our routes

export function Router() {
  const navContext = useContext(NavContext);

  switch (navContext.current.path) {
    case 'cockpit':
      return (
        <Cockpit/>
      );
    default:
      return <header>
        <Navbar/>
      </header>
  }
}

Under the hood?

export function NavProvider({children, entryPath}) {
  const [current, setCurrent] = useState({path: entryPath, params: {}});
  const [history, setHistory] = useState([current]);

  const loadFromHash = () => {
    const pathFromHash = window.location.hash.split('#')[1]
    setCurrent({path: pathFromHash});
    setHistory([{path: pathFromHash}])
  }

  useEffect(() => {
    window.addEventListener("hashchange", e => loadFromHash());
    loadFromHash();
  }, []);

  const updateCurrent = ({path, params}) => {
    window.location.hash = `${path}`;
    setCurrent({path, params});
  }

  const push = (path, params) => {
    setHistory(prev => [...prev, {path, params}]);
    updateCurrent({path, params});
  }

  const back = () => {
    history.pop();
    const previousItem = history[history.length - 1];
    setHistory(history);
    updateCurrent(previousItem);
  }

  return <NavContext.Provider value={{ setCurrent: updateCurrent, current, push, back }}>
    {children}
  </NavContext.Provider>;

}

Does your component need access to params?

No problem!

export function Cockpit() {
  const {current} = useContext(NavContext);
  const navParams = current.params;

  return <p>{JSON.stringify(navParams)}</p>
}

Do you want to navigate back and forth?

No problem! You can just use the push and back API from our NavContext.

Conclusion

In most cases, you should go with react-navigation. It will save you a lot of time and just don't reinvent the wheel. However, within a side project that has just too few features to matter, you might learn a lot about routing from implementing it yourself.