reactjsreact-hooksreact-routersemantic-ui

Page Not Displaying


I am stuck on this problem for days and the solutions that I find on the web are not helpful. My routes are not working properly. The URI is updating, but the appropriate pages are not displaying according to the path. When I refresh the browser, only then, the appropriate page comes through. Otherwise, only the home page is displayed, even when the path changes.

I will do my best to exhaust the codes here:

package.json

...
"history": "^5.3.0",
"node-sass": "^8.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.8.1",
...

AppRoutes.js

import { useRoutes } from 'react-router-dom';
...

const AppRoutes = () => {
    const routes = useRoutes([
        { path: PATH.home, element: <page.Home /> },
        { path: PATH.defect, element: <page.Defect /> },
        { path: PATH.other, element: <page.Other /> },
        { path: PATH.allRoutes, element: <page.Home /> }
    ]);

    return routes;
}

Navbar.js

...
import history from '../../utils/BrowserHistory';
...

/**
 * I am using semantic UI menu
 * Here I push the path for a browser route change
 */
handleItemClick = (e, { name }) => {
        this.setState({ activeItem: name });

        switch (name) {
            case APP_CONST.home:  
                history.push(PATH.home);
                break;
            case APP_CONST.defect:
                history.push(PATH.defect);
                break;
            case APP_CONST.other:
                history.push(PATH.other);
                break;
            default:
                history.push(PATH.home);
                break;
        }
    }
...

render() {
        const { activeItem } = this.state;

        return (
            <Fragment>
                {
                    this.state.width <= NUMBER.mobileScreenSize ?
                        <MobileNav
                            onToggle={this.handleToggle}
                            visible={this.state.visible}
                            onPusherClick={this.handlePusher}
                            item={activeItem}
                            handleItemClick={this.handleItemClick}
                        >
                            <NavBarChildren>{this.props.children}</NavBarChildren>
                        </MobileNav> :
                        <DesktopNav item={activeItem} handleItemClick={this.handleItemClick}>
                            <NavBarChildren>{this.props.children}</NavBarChildren>
                        </DesktopNav>
                }
            </Fragment>
        )
    }
}

const NavBarChildren = props => (
    <Container>{props.children}</Container>
);

DesktopNav.js

export const DesktopNav = props => {

    const { item, handleItemClick, children } = props;

    return (
        <React.Fragment>
            <Menu fixed='top' pointing secondary>
                <Menu.Menu>
                    <MenuItems item={item} handleItemClick={handleItemClick} />
                </Menu.Menu>
            </Menu>
            <div className='desktop-menu-items'>{children}</div>
        </React.Fragment>
    );
}

App.js

imports ...

function App() {
  return (
    <NavigationBar>
      <AppRoutes />
    </NavigationBar>
  )
}

index.js

...
import { BrowserRouter } from 'react-router-dom';
import history from './utils/BrowserHistory';
...

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <BrowserRouter history={history}>
        <App />
    </BrowserRouter>
);

Please assist, thanks in advance...


Solution

  • The BrowserRouter doesn't consume a history prop. The BrowserRouter maintains its own internal history reference, and so isn't aware of the URL changes your custom history object makes.

    If you are effecting navigation actions from the custom history object in that Navbar component instead of using Link components then you'll need to use a router that can take the custom history object so it can synchronize the routes it manages with the URL changes the history object effects.

    You can import the HistoryRouter, which does consume a history prop.

    Example:

    ...
    import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom';
    import history from './utils/BrowserHistory';
    ...
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <HistoryRouter history={history}>
        <App />
      </HistoryRouter>
    );