Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use react without a router component

If I want to make a web application using reactjs that is not a single page. Should I compile all the react code into a single file and load it on all pages of the application, then use the function that I expose to render the necessary components?

Example of an html file

<div id="Clock" data-react="Clock"></div>
<div id="HelloWorld" data-react="HelloWorld"></div>

example of index.js

import React from 'react';
import ReactDOM from 'react-dom';
import Clock from './Clock';
import HelloWorld from './HelloWorld';
import OtherComponent from './OtherComponent';

const APPS = {
    Clock,
    HelloWorld,
    OtherComponent
};

const MyReactRender = react => {

    let component = react.getAttribute('data-react');
    let App = APPS[component];

    if(App != undefined) {
        ReactDOM.render(<App />, document.getElementById(component));
    }
}

document.querySelectorAll('[data-react]').forEach(MyReactRender);
like image 764
MrGilbertMan Avatar asked Sep 01 '17 15:09

MrGilbertMan


2 Answers

I'd see two ways, of increasing quality and difficulty. In both cases, you use good old anchors elements to redirect the page to a url, to which different templates correspond.

  • Manually check for the existence of divs id's

In this case, each template includes the same javascript bundle that contains everything in the app and a single element with an id corresponding to the specific component. The idea is to check wether or not an element is present in the page, then activate its corresponding react component if it is.

if (document.getElementById('component-root')) {
  ReactDOM.render(<Component />, document.getElementById('component-root'));
}

On the up side, it's quite easily implemented. On the down side, the bundle will always get bigger and bigger, and the list of ifs grows each time you add a new "page".

  • Separate your modules in actual bundles

Different bundle managers exist, but I'd recommend using Webpack to create multiple bundles that contain only specific part of your application. Then, each template contains only the corresponding div element, as well as that specific bundle.


<head><script src="/js/clock.js"></head>
<body><div id="root-clock"></div></body>

<head><script src="/js/otherComponent.js"></head>
<body><div id="root-other-component"></div></body>

How to package multiple bundles with webpack is out of the scope of this answer, but look here.

like image 55
Félix Adriyel Gagnon-Grenier Avatar answered Sep 22 '22 17:09

Félix Adriyel Gagnon-Grenier


I've tried making a react application without a router. I used ternary operators to switch from component to component.

// App Component
class App extends Component {
  constructor(props) {
    super(props)

   this.state = {
      inClockComponent: true,
      inHelloWorldComponent: false,
      inOtherComponent: false
   }

  }


 render() {
    const {inClockComponent, inHelloWorldComponent, inOtherComponent} = this.state
    return (
      <div>
      {

      inClockComponent 
        ? <Clock> : inHelloWorldComponent 
          ? <HelloWorld> : inOtherComponent ? <OtherComponent> : 
              <div>No Component Here</div>

      } 
     </div>
  }

You could pass a function from the App component that would change the display state to each child component of App

Example

// in App Component
 showHelloWorldComponent() {
     this.setState({
        inClockComponent: false,
        inHelloWorldComponent: true,
        inOtherComponent: false
     )}
 }

You insert that function onto a button that would navigate to a different component

Example

// in Clock Component

render() {
  return (
    <div>
      <h2>Time is 5:15 P.M.</h2>
      <button onClick={this.props.showHelloWorldComponent}>
         Go To Hello World
      </button>
  )
}

It's a messy solution, and I wouldn't suggest using it in a big application, but I hope this answers your question!

like image 32
Tomy Avatar answered Sep 19 '22 17:09

Tomy