3

Using <Link to="/projects/some-project-slug" /> does change the URL in the browser, but the app does not change its display.

Here is the the app:

import React from 'react';
import { Router } from "@reach/router"

import HeaderNavItems from '../../constants/header-nav-items';

import Header from '../header/header';
import Footer from '../footer/footer';

import AboutView from '../../views/about/about-view';
import NotFoundView from '../../views/not-found/not-found-view';
import ProjectDetailsView from '../../views/project-details/projects-details-view';
import ProjectsIndexView from '../../views/projects-index/projects-index-view';

import config from '../../config.json';


import './app.scss';


const App = () => {
  const { common } = config;

  // component
  return <div className="app">
    <Header
      heading={ common.heading }
      subheading={ common.subheading }
      navItems={ HeaderNavItems }
    />
    <Router>
      <ProjectsIndexView path='/' />
      <ProjectsIndexView path='/projects' />
      <ProjectDetailsView path='/projects/:projectSlug' />
      <AboutView path='/about' />
      <NotFoundView default />
    </Router>
    <Footer
      heading={ common.heading }
      subheading={ common.subheading }
    />
  </div>
};

export default App;

And here is the component that contains a <Link/> (which is instantiated in <ProjectsIndexView/>):

import React from 'react';
import { Link } from '@reach/router';

import themeModel from '../../models/ThemeModel';

import './project-teaser.scss';


const ProjectTeaser = (props) => {
  const render = () => (
    <Link
      className={ `project-teaser ${themeModel.current}` }
      to={ props.href }
    >
      <img
        className="image"
        src={ props.imageSource }
        alt=""
      />
      <div className="project-name">
        { props.name }
      </div>
    </Link>
  );

  return render();
}

export default ProjectTeaser;

The URL in props.href is correct. If I refresh the browser at the URL to which the redirected, then only does the view work. I am trying to ensure NOT to need a page refresh.

I do need that both / and /projects use the same component, as I do not want visitors to be thrown to the <NotFound/> in case they go to /projects directly.

This issue seemed similar, however they are causing the redirect in code, whereas I am using a <Link/>.

Any guidance and respectful answer will be appreciated.

UPDATE

The <ProjectTeaser/> component is defined in an external library. There are 3-4 projects using this component. For fun, I tried to copy the component definition in the same project that consumes it, which meant it was no longer imported from an external library.

And now the routing works.

Can anyone explain to me how this happens? It's the same code! Just located in different projects. The only difference I see is that the library version is precompiled.

However, if this is working as the @reach/router library expects, it's greatly inconvenient, as I am trying to avoid to have to copy the <ProjectTeaser/> definition in every project that needs it.

jansensan
  • 633
  • 1
  • 8
  • 23

1 Answers1

0

I found that @reach/router was being included in the page twice. In the main project it's being included as a dependency and in external library it's being included as a devDependency.

Here's an example of the directory structure,

+-- main_project_path
|   +-- node_modules
|       +-- external_lib      <-- [linked]
|       +-- @reach/router
|
+-- external_lib
|   +-- node_modules
|       +-- @reach/router

To fix it I linked @reach/router within the main projects node_modules.

cd ~/main_project_path/node_modules/@reach/router
yarn link

cd ~/path_to_external_lib/
yarn link @reach/router
Dharman
  • 30,962
  • 25
  • 85
  • 135