Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using React in a multi-page app

People also ask

Is react good for multi page application?

The use cases for having multiple pages in a single React app are pretty simple. You can create a website, and easily classify different types of content on different pages. But, it should also be understood that the default implementation of React is made to use a single HTML file, and this is by design.

How do I create a multiple page app with react?

Create Multiple Page Application in React First, we create a new project in the terminal by typing npx create-react-app new-project , then we navigate to the app folder and start the app using npm start . In the src folder of the project, we create the following files: Home. js.

Is react a single page app or multi page?

ReactJs Control over entire Applications In single page applications, our page is built with components and every component is a React Component and also the entire page is managed by root React component and it's just under React control.


Currently, I am doing something similar.

The application is not a full React App, I am using React for dynamic Stuff, like CommentBox, which is autark. And can be included at any Point with special params..

However, all my sub Apps are loaded and included into a single file all.js, so it can be cached by the browser across pages.

When I need to include an App into the SSR Templates, I just have to include a DIV with the class "__react-root" and a special ID, ( the name of the React App to be rendered )

The logic is really simple:

import CommentBox from './apps/CommentBox';
import OtherApp from './apps/OtherApp';

const APPS = {
  CommentBox,
  OtherApp
};

function renderAppInElement(el) {
  var App = APPS[el.id];
  if (!App) return;

  // get props from elements data attribute, like the post_id
  const props = Object.assign({}, el.dataset);

  ReactDOM.render(<App {...props} />, el);
}

document
  .querySelectorAll('.__react-root')
  .forEach(renderAppInElement)

<div>Some Article</div>
<div id="CommentBox" data-post_id="10" class="__react-root"></div>

<script src="/all.js"></script>

Edit

Since webpack perfectly supports code-splitting & LazyLoading, I thought it make sense to include an example where you don't need to load all your apps in one bundle, but split them up and load on demand.

import React from 'react';
import ReactDOM from 'react-dom';

const apps = {
  'One': () => import('./One'),
  'Two': () => import('./Two'),
}

const renderAppInElement = (el) => {
  if (apps[el.id])  {
    apps[el.id]().then((App) => {
      ReactDOM.render(<App {...el.dataset} />, el);
    });
  }
}

You can provide several entry points for the application in the webpack.config.js file:

var config = {
  entry: {
    home: path.resolve(__dirname, './src/main'),
    page1: path.resolve(__dirname, './src/page1'),
    page2: path.resolve(__dirname, './src/page2'),
    vendors: ['react']
  },
 output: {
    path: path.join(__dirname, 'js'),
    filename: '[name].bundle.js',
    chunkFilename: '[id].chunk.js'
  },
}

then you can have in your src folder three different html files with their respective js files (example for page1):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Page 1</title>
</head>
<body>
  <div id="app"></div>
  <script src="./vendors.js"></script>
  <script src="./page1.bundle.js"></script>
</body>
</html>

JavaScript file:

import React from 'react'
import ReactDom from 'react-dom'
import App from './components/App'
import ComponentA from './components/ReactComponentA'
ReactDom.render(<div>
                  <App title='page1' />
                  <ReactComponentA/>
                 </div>, document.getElementById('app'))

Different React components can be then loaded for each single page.


I'm building an application from the ground up and am learning as I go, but I think what you are looking for is React-Router. React-Router maps your components to specific URLs. For example:

render((
    <Router>
        <Route path="/" component={App}>
            <Route path="api/animals" component={Animals}>
               <Route path="birds" component={Birds}/>
               <Route path="cats" component={Cats}/>
            </Route>
        </Route>
        <Route path="api/search:term" component={AnimalSearchBox}>
    </Router>
), document.body)

In the search case, 'term' is accessible as a property in the AnimalSearchBox:

componentDidMount() {
    // from the path `/api/search/:term`
    const term = this.props.params.term
}

Try it out. This tutorial is the one that put me over the top in terms of my understanding of this and other related topics.


Original answer follows:

I found my way here looking for the same answer. See if this post inspires you. If your application is anything like mine, it will have areas that change very little and varies only in the main body. You could create a widget whose responsibility it is to render a different widget based upon the state of the application. Using a flux architecture, you could dispatch a navigation action that changes the state your body widget switches upon, effectively updating the body of the page only.

That's the approach I'm attempting now.


Are you using a CMS? They tend to like changing urls which could break your application.

Another way is using something like React Habitat.

With it, you can register components and they automatically get exposed to the dom.

Example

Register component(s):

container.register('AnimalBox', AnimalBox);
container.register('AnimalSearchBox', AnimalSearchBox);

Then they are availiable in your dom like this:

<div data-component="AnimalBox"></div>

<div data-component="AnimalSearchBox"></div>

The above will be automatically replaced with your react components.

You can then automatically pass properties (or props) to your components too:

<div data-component="AnimalBox" data-prop-size="small"></div>

This will expose size as a prop to your component. There are additional options for passing other types such as json, array's, ints, floats etc.