52

I'm new to React. I'm much more familiar with Angular2+. In Angular, every component has a separate html file. However, in React, I see that render function itself includes the html template. For example,

import React, { Component } from 'react';

class HelloWorld extends Component {
    render() {
        return (
            <h2> Hello World </h2>
        );
    }
}

export default HelloWorld;

Well I want to take

<h2> Hello World </h2>

outside the js file and put it in a separate html and import the html file to render function, for example

 render() {
            return (
                import content of helloworld.html
            );
        }

Do you know how to do it?

CrazySynthax
  • 13,662
  • 34
  • 99
  • 183
  • 2
    By keeping your components small and lightweight and extracting logic into smart components there shouldn't be a need to do that. This is an intentional choice by the react developers. Is there a special reason you want to do this or just because of habit? – trixn Aug 09 '17 at 21:48
  • Related: [How can I render HTML from another file in a React component?](https://stackoverflow.com/questions/33973757/how-can-i-render-html-from-another-file-in-a-react-component) – AlikElzin-kilaka May 01 '18 at 08:17

5 Answers5

23

In React you would typically make a child component and import it into the parent component.


Since your child component here would just be static markup i.e <h2>Hello World</h2>, you don't need to worry about component state.

Therefore, you could do the following:

  1. make a functional (aka stateless or dumb) component for your text. You could name it HelloWorldText as an example.

  2. import this functional component into your parent component HelloWorld.


Your functional component would look something like this:

HelloWorldText.js

const HelloWorldText = () => ( <h2> Hello World </h2> );

export default HelloWorldText;

Then you would import this functional component HelloWorldText into your parent component HelloWorld like so:

HelloWorld.js

import React, { Component } from 'react';
import HelloWorldText from './path/to/HelloWorldText';

class HelloWorld extends Component {
  render() {
    return (
      <HelloWorldText />
    );
  }
}

export default HelloWorld;

Here's a CodePen Demo with this code.

Unfortunately on CodePen you can't export and import components, but hopefully it still gives you an idea on how to use a child component inside a parent component.



Note: In React you want your components to be as general as possible. You would probably end up making a Text component instead of a HelloWorldText component.

Then you would pass text dynamically into the Text component using props.

Here is a CodePen Demo of this in action.

Dan Kreiger
  • 5,358
  • 2
  • 23
  • 27
  • 7
    yes, nicely explained answer, but still is there any way to import HTML file instead of directly write code in the render method ? – Pardeep Jain Aug 10 '17 at 05:25
  • 1
    I think to do this you would have to use React's [`dangerouslySetInnerHTML`](https://facebook.github.io/react/docs/dom-elements.html) prop. This [stackoverflow answer](https://stackoverflow.com/questions/33973757/how-can-i-render-html-from-another-file-in-a-react-component) describes how to do this. – Dan Kreiger Aug 10 '17 at 08:15
  • 1
    *Unfortunately on CodePen you can't export and import components".. but, with Codesandbox you can: https://codesandbox.io/s/4jyljlwp74 – Carol Skelly Aug 27 '18 at 20:53
  • @DanKreiger inside HelloWorldText.js how can we create functions to allow an onClick function? – JayC Aug 06 '21 at 14:12
  • @Jesse you can use an onClick hander in the JSX code. Then you just pass the function you want to this onClick handler. Here is a demo: https://codesandbox.io/s/jovial-antonelli-lffc7?file=/src/HelloWorldText.js:26-33 – Dan Kreiger Aug 06 '21 at 19:41
  • So unlike angular, you can't define the template in a separate html only file? – scott.korin Oct 14 '22 at 16:34
14

You can move the JSX part into a separate file and import that file in your component class

Here's an example

Signin.jsx

 import React from 'react';

 export const SigninJsx = () => {
 return (
 <div className="container">
        <form className="form-signin">
            <h2 className="form-signin-heading"> Please sign in </h2>
            <br />
            <label htmlFor="inputEmail" className="sr-only"> Email address
            </label>
            <input type="email" id="inputEmail" onChange={this.handleEmailChange} className="form-control" placeholder="Email address" required autoFocus />
            <br />
            <label htmlFor="inputPassword" className="sr-only"> Password</label>
            <input type="password" id="inputPassword" onChange={this.handlePasswordChange} className="form-control" placeholder="Password" required />
            <br />
            <button className="btn btn-lg btn-primary btn-block" onClick={this.signIn} type="button"> Sign in
            </button>
        </form>
    </div>
)
}

Signin.js

import React, { Component } from 'react';
import {SigninJsx} from './Signin.jsx';

export class Signin extends Component {
constructor(props){
    super(props);
    this.handleEmailChange = this.handleEmailChange.bind(this);
    this.handlePasswordChange = this.handlePasswordChange.bind(this);
    this.state = {
        email:'',
        password:''
    };
    this.signIn = this.signIn.bind(this)
}

handleEmailChange(e){
    this.setState({email:e.target.value})
    console.log("Error Change");
}
handlePasswordChange(e){
    this.setState({password:e.target.value})
}

signIn(){
    alert('Email address is ' + this.state.email + ' Password is ' + this.state.password);            
}

render() {
    return (
        <SigninJsx />
    )
}

 }
Paras Mathur
  • 172
  • 1
  • 5
  • 2
    Thank you for this. When I try to reference [this.state.email] from the template (SignIn.jsx) I get an error stating that [this] is undefined. Similar happens if I try to reference [state.email]. Would you know why? – Jelgab Jun 13 '20 at 21:46
  • if you use this you can use return SigninJsx(this) instead look at this https://stackoverflow.com/a/42455698/1427338 – Jeffrey Nicholson Carré Jul 27 '20 at 05:45
  • 1
    @Jelgab because this answer is incorrect and instead of splitting component into class and template like Angular does it just renders one component inside another. React has no built in support for separating the template. A 3rd party template implementation would be required for that. – fires3as0n Sep 20 '22 at 21:56
3

Please checkout this Medium link

This will be your React component declaration and you need to import the template.js file inside here and render it in context of the component 'Abc' (index.jsx):

import template from './template';

export default class Abc extends React.Component {
  render() {
    return template.call(this)
  }
}

Separate js file will have template as follows (template.js):

import styles from './styles.module.css';

const template = () => (
<div className={styles.outerContainer}>
  <div className={styles.middleContainer}>
        <div className={styles.innerContainer}>Hello, World</div>
    </div>
</div>
);
export default template;

Additionally, we can import CSS modules inside the template and maintain them in serapate file as well, as follows (styles.module.css):

.outerContainer {
  backgroundColor: red;
} 
/* etc... etc... */
Srikanth Sharma
  • 1,509
  • 2
  • 15
  • 27
2

for now , it is not possible to load template from html file.

javad hemati
  • 236
  • 1
  • 2
  • 6
0

Using TypeScript for my project the other solutions don't really work since the properties inside the template (like {this.someProperty}) throw errors if someProperty is not in the same class.

What I ended up doing was extending the components class and putting the render function in the subclass:

app/components/HelloWorld.ts:

import React from 'react';

export abstract class HelloWorld extends React.Component<{},{}> {

    public state = {
        label: 'Hello World'
    };

    constructor(props) {
        super(props);
    }

    public componentDidMount():void {
        tr('Hello World mounted');
    }

    // ... more code and handlers here..

}

app/components/HelloWorld.r.tsx: (the r is arbitrary but the file name needs to differ from the *.ts file)

import { HelloWorld as HelloWorldComponent } from './HelloWorld';

export default class HelloWorld extends HelloWorldComponent {

    public render() {
        return (
            <>
                <h2>{this.state.label}</h2>
            </>
        );
    }
}

You can now import the component wherever you like like this:

  import HelloWorld from 'app/components/HelloWorld.r';

Hope this solution helps those looking for a TypeScript solution

Arno van Oordt
  • 2,912
  • 5
  • 33
  • 63