Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"How to Implement Routing and Navigation" - is this still correct? #748

Closed
richb-hanover opened this issue Jul 15, 2016 · 13 comments
Closed

Comments

@richb-hanover
Copy link

The "How to Implement Routing and Navigation" page at https://github.com/kriasoft/react-starter-kit/blob/master/docs/recipes/how-to-implement-routing.md appears to describe an earlier (non-universal-router) version of ReactStarterKit.

According to CHANGELOG.md, the components moved to src/routes, while the page above still refers to them in src/components. It appears that all the signatures of the functions/components changed, as well.

The project might use universal-router, but the last sentence of the API doc ("Sorry, the rest of the guide is currently under development. Come back soon.") doesn't give a strong sense of confidence.

@koistya
Copy link
Member

koistya commented Jul 15, 2016

Good catch! I will update the docs. In meanwhile, here is the outline how routing works (with the difference that RSK supports nested routes) - You might not need React Router on Medium.com

@richb-hanover
Copy link
Author

richb-hanover commented Jul 15, 2016

Thanks for the speedy response. I have learned more after I wrote the original post. I found a critical sentence in the Getting Started page for universal-router at https://github.com/kriasoft/universal-router/blob/master/docs/getting-started.md:

... the resolve function ... is responsible for traversing the list of routes, until it finds the first route matching the provided URL path string and whose action method returns anything other than undefined. Each route is just a plain JavaScript object having path, action, and children (optional) properties.

So "all I need to do" in RSK is have each page/component's index.js page export a default object with a path, action, and optional children property. If resolve() matches on the path (or path+child), action() gets called and returns a string, including the expansion of React templates.

I think... is this true?

@richb-hanover
Copy link
Author

richb-hanover commented Jul 15, 2016

NB The example just below the cited paragraph has an error, I think. The example should render "<h1>Page One</h1>", but the comment in the example says "// renders: <h1>Post #123</h1>"

@koistya
Copy link
Member

koistya commented Jul 15, 2016

@richb-hanover there are two important notions about universal-router module, as opposed to react-router it just handles routing itself and is supposed to be used in combination with a navigation library, the history module can be used for that. Another concept is that the router doesn't care about what route handler functions (actions) return. The router just finds the first matching route, gets the result from its action method and if the result is not null or undefined, returns it to a caller. For example:

var routes = [
  { path: '/', action: () => 'home page' },
  { path: '/hello', action: () => 123 }
];
var result1 = await Router.resolve(routes, { path: '/' }); // resolve() returns a Promise
// result1 => "home page"
var result2 = await Router.resolve(routes, { path: '/hello' }); // resolve() returns a Promise
// result2 => 123

The way RSK is currently configured, it uses this convention that route handlers (actions) should return React components. E.g. { path: '/hello', action: () => <HelloPage /> }.

Since route handlers are not very concise, it might be a good idea to split routes into multiple files:

const routes = [
  require('./routes/home'),
  require('./routes/tasks'),
];

This way you can have React component and routing information collocated within the same folder.

...

You can also use another convention if you like. For example, put all routes into the same file. Or, make the route handlers return more data, e.g.:

 {
  path: '/tasks/:id',
  async action({ params }) {
    const resp = await fetch(`/api/tasks/${params.id}`);
    const data = await resp.json();
    return { title: `To-Do (${data.length})`, component: TodoList, props: data };
  }
}

or, pass render and redirect functions to the route handlers, e.g.

const routes = [
  {
    path: '/hello',
    action({ render }) {
      return render(<HelloPage />);
    }
  }
];

Router.resolve(routes, { path: '/hello': render: ... });

@richb-hanover
Copy link
Author

That is useful information for understanding the current state of RSK.

A follow-on question: I want to have an /api module that has several sub-paths (/api/AAA, /api/BBB/, /api/CCC, etc.) In RSK 0.5.1, I previously had a separate file with a number of router.get() calls.

It sounds as if this should become another file ( src/routes/api/api.js) that exports its own default object for each of the paths.

Some of the responses to the /api calls will be JSON, some will be bare text, some might be HTML. How (in the RSK framework) do I get a handle to the response to send the data back? Thanks!

@richb-hanover richb-hanover changed the title "How to Implement Routing and Navigation" - is this totally wrong? "How to Implement Routing and Navigation" - is this still correct? Jul 15, 2016
@koistya
Copy link
Member

koistya commented Jul 15, 2016

@richb-hanover here is pattern that you may want to use, for each RESTful API endpoint create a separate file inside the src/api folder. For example:

src/api/tasks.js
import { Router } from 'exrpess';
import { Task } from '../data/models'; // Sequelize ORM models

const router = new Router();

// HTTP GET /api/tasks/123
router.get('/:id', async (req, res, next) => {
  try {
    const task = await Task.findOne({ id: req.params.id });
    res.send(task);
  } catch (err) {
    next(err);
  }
});

// HTTP GET /api/tasks
router.get('/', async (req, res, next) => {
  try {
    const tasks = await Task.findAll();
    res.send(tasks);
  } catch (err) {
    next(err);
  }
});

module.exports = router;

Then register that file in server.js as an Express middleware.

app.use('/api/tasks', require('./api/tasks'));

Refer to Express documentation for more info: http://expressjs.com/

@richb-hanover
Copy link
Author

Shouldn't the final app.use('/tasks',... use /api/tasks as the parameter? Thanks.

@koistya
Copy link
Member

koistya commented Jul 15, 2016

@richb-hanover yep, right.

@richb-hanover
Copy link
Author

I issued a PR for a placeholder page to update the How to Implement Routing page:

a050029

@drobertson123
Copy link

A quick note. Really like the "Why this is better" note in the PR.

Speaking for myself, I am still learning a lot about the React ecosystem. Having a few lines explaining what the role of the code is and why it was done that way is a huge help to put things in context.

A small section focused on that as people do the docs is very appreciated.

@shekaryenagandula
Copy link

routing not working for me.
Showing the error " internal server error "
Here is my code
The files view:
image

adding path to route

    {
       path: '/hellopage',
       load: () => import(/* webpackChunkName: 'home' */ './hellopage'),
     },

src\routes\hellopage\index.js

 import React from 'react';
 import HomePage from './HomePage';

 function action() {
   return {
     title: 'HomePage title',
     component: <HomePage />,
   };
 }

 export default action;

src\routes\hellopage\HelloPage.js


import React from 'react';

class HelloPage extends React.Component {
  render() {
    return (
      <h1>
        <h1>Welcome!</h1>
        <p>Here your can learn more about our product.</p>
        {console.log("Something went wrong")}
      </h1>
    );
  }
}
export default HelloPage;

Getting below error in browser
Failed to compile
./src/routes/hellopage/index.js
Module not found: Can't resolve './HomePage' in 'C:\Users\yenag\Desktop\TestApp\src\routes\hellopage'

Please help. All the docs are seems like out dated and unable to find any solution on internet.
Thanks

@mmarkelov
Copy link

@shekaryenagandula seems like that you have typo. In your src\routes\hellopage\index.js you tried to import HomePage, but in your folder you don't have it. I suppose you should import HelloPage instead

@ulani
Copy link
Member

ulani commented May 27, 2021

@richb-hanover thank you very much for crating this issue! Unfortunately, we have close it due to inactivity. Feel free to re-open it or join our Discord channel for discussion.

NOTE: The main branch has been updated with React Starter Kit v2, using JAM-style architecture.

@ulani ulani closed this as completed May 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants