I am in the process of migrating my pages from html and jquery to using React and I am aware that React Router and Redux are methods to handle routing when building a react application, but for the time being, I was wondering how I can change my setup to be able to render different react components for different pages. At the moment, I am able to render one react component when my index page is loaded, but I thought I could add another ReactDOM.render() beneath it and target a different div id for the component on a different page, but I noticed an error, Invariant Violation: Target container is not a DOM element. Is this related to not using a react router or something else?
here is my index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import ActivityFeed from './components/App/ActivityFeed/ActivityFeed';
import CreateAnnotation from './components/App/Annotation/CreateAnnotation';
ReactDOM.render(<ActivityFeed />, document.getElementById('annotation-card'));
ReactDOM.render(<CreateAnnotation />, document.getElementById('annotation-form'));
Here is <CreateAnnotation/>:
import React from 'react';
//GET /api/activity-feed and set to state
export default class CreateAnnotation extends React.Component {
constructor(props, context) {
super(props, context);
this.state = this.context.data || window.__INITIAL_STATE__ || {
notifications: [],
reportLinks: [],
files: []
}
}
render() {
return (
<div>
<p>test</p>
</div>
)
}
}
Here is the view file:
<!DOCTYPE html>
<head>
{{> app/app-head}}
</head>
<body>
<div id="annotation-form"></div>
{{> general/bundle-js}}
</body>
</html>
{{> general/bundle-js}}:
<script src="/bundle.js"></script>
ReactDOM renders a React element into the DOM in the supplied container
and return a reference to the component (or returns null for stateless
components). If the React element was previously rendered into
container , this will perform an update on it and only mutate the DOM
as necessary to reflect the latest React element.
Technically speaking you cant render more than one React element into the DOM with multiple ReactDOM render function as it would always replace the previous rendered DOM.
See https://reactjs.org/docs/react-dom.html
The right way to do is to create multiple components and import them into App.js file. Then, your index.js file is supposed to import App.js file
as one whole component, with ReactDOM only renders App.js as a single component.
Related
I just watched a talk from React Conf 2018. In the video, the speaker shows 2 ways to set the document title. The first is by using the Lifecycle methods (componentDidMount and componentDidUpdate) if we use a class component, the second one is by using the useEffect hook if we use a function component. It looks like that's the recommended way to do it according to answers from this question.
But, I tested the following code and it seems to work just fine to set the document title directly:
import React from 'react';
import ReactDOM from 'react-dom';
function App() {
document.title = 'wow'
return <p>Hello</p>
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
The title changed:
Is there any significance of setting the document title inside useEffect or componentDidMount?
Or is it because it was the only way to set the document title?
Is it okay to set the document title directly like I did in the snippet above?
Update:
It also works with class component:
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
render() {
document.title = 'wow'
return <p>Hello</p>
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
The thing is, the render function in React, is considered to be a pure function.
A pure function should not have any side-effects. Eventually updating the document.title means that you are referencing the document directly from render-> which is already considered a side effect.
Render should mainly do one thing -> render some JSX, if there is a need to do some API calls/interact with the document/window etc..., this should be placed in componentDidMount/componentDidUpate for a class Component, OR in a useEffect/useLayoutEfect for a functional component based on hooks.
(useEffect for e.g. is a function that runs asynchronously, and updating the document title from it will not block the rendering, whereas doing it directly will block it.)
Use react-helment which is also widely used in other frameworks with the same name as helmet express ...
Here is the same code:
import {Helmet} from "react-helmet";
class Application extends React.Component {
render () {
return (
<div className="application">
<Helmet>
<meta charSet="utf-8" />
<title>My Title</title>
<link rel="canonical" href="http://example.org/example" />
</Helmet>
...
</div>
);
}
};
Another way to use via props to which is cleaner IMO
...
<Helmet titleTemplate={`%s | ${props.title}`} defaultTitle={constants.defaultTitle} />
You may also use react-helmet-async for more features.
I have a site that is not a spa. At one point when a button is click a div is created in the dom. After the div is created I want to render a React component into this div. My component looks like this
import React, { Component } from 'react';
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
date: null
};
}
render() {
return (
<div>
//Here will be more controls
</div>
);
}
}
I'm running webpack on this file and in my original page I'm referencing the generated js file.
What code should I add to my button click code that is adding the div so I can render the component?
ps. Actually the functionality is a bit more complex, because we are scraping a page the user specifies and showing the html in an iframe through the srcdoc attribute. The scraped html has the div added and then we render a widget in the div so the user can preview what our widget would look like on their page.
You have to use ReactDOM to render the component. Install and import react-dom in your project so that webpack bundles it for you. You might need to expose ReactDOM as global in your web pack configuration.
Below is a simple code snippet:
ReactDOM.render(
<MyComponent/> ,
document.getElementById(id) // id of element in your case div created
);
Reference
https://reactjs.org/docs/react-dom.html
This question already has an answer here:
import from base component can't find variable
(1 answer)
Closed 4 years ago.
I've just started to learn React and I would like to create simple page with form. Form should contain inputs keywords and city, select list date and submit buttom.
It's structure of my project
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Application</title>
</head>
<body>
<div id="root">
<div class="form-container"></div>
</div>
</body>
</html>
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import './bootstrap.min.css';
import './SearchForm.js';
SearchForm.js
const formContainer = document.querySelector('.form-container')
class SeacrhForm extends React.Component {
constructor(props) {
super(props)
this.state = {
keywords: '',
city: '',
date: ''
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
render() {
return (
<form className='search-form' onSubmit={this.handleSubmit}>
<h1>Say Hi!</h1>
</form>
)
}
}
ReactDOM.render(<SeacrhForm />, formContainer)
And I got errors on my page in browser
What did I do wrong?
Okay You need to add the following imports to you searchform.js file
import React from 'react';
import ReactDOM from 'react-dom';
and remove this line:
const formContainer = document.querySelector('.form-container')
And don't change the index.html file ever, instead create a new component like you have created searchform.js and render it in app.js and then react will automatically render that component inside
<div id=root></div>
you may not need to manually do it.
check out the following link, It may help you to understand reactJs better.
https://reactjs.org/docs/hello-world.html
Add
import React from 'react'
import ReactDOM from 'react-dom'
to SearchForm.js
Modern JS works well with ES modules, that means that you need to import dependencies into every file(module), otherwise such libraries will not be available.
I just started working in ReactJS and I was going through a basic React tutorial.
I have created a project and added Babel, React, ReactDOM, Webpack, Express as the dependencies.
Now I have this Counter.js :
import React, {Component} from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = {count: 0};
}
render() {
return (
<button onClick={() => {this.setState({ count: this.state.count + 1 });}}>
Count: {this.state.count}
</button>
);
}
}
export default Counter;
And the main.js (which is defined as the entry point of the application in webpack.config.js file):
import React from 'react';
import ReactDOM from 'react-dom';
import Counter from './Counter.js';
ReactDOM.render(<Counter/>,document.getElementById("warbox"));
The PROBLEM is that when I start up the application, the component is not rendered on the page AND also the React DevTool Chrome extension doesn't light up (if that makes any sense).
Can't seem to figure out the problem exactly. Any help is appreciated. Apologies if its too basic.
The index.html :
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="warbox"></div>
<script src="bundle.js"></script>
</body>
</html>
UPDATE : Solved. I think I should update what made it work for others to see. Heres the problem I had : Apparently the bundle.js needs to be updated by running the webpack explicitly. After making the changes, I had to stop the server and run the webpack and restart the server. It WORKED!
i'm using spring boot and my index.html is in src/main/resources/templates directory and below is the content. If i render a static content from html itself it renders but when i try to render from react component it doesn't render anything
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<meta charset="UTF-8"/>
<title>ReactJS + Spring Data REST</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react-dom.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="react"></div>
<script src="built/bundle.js"></script>
</body>
</html>
my react component is in src/main/js/ directory and app.js file
Below is the all the codes i have in the app.js file
import React from 'react';
import {render} from 'react-dom';
import RendorTest from 'components/RendorTest';
class RendorTest extends React.component{
rendor(){
return(
<div><h1>Spring Boot + Rest + React.js</h1></div>
);
}
}
var element = <RendorTest />;
ReactDOM.render(
element,document.getElementById('react')
)
I'm not sure why you're importing RendorTest and then declaring another class of the same name, but you are also extending the wrong method on the React object. You need to extend React.Component { } not .component.
You could also import React, { Component } from "react"; and then extend Component { }
As ahutch mentioned, you also need to call the render() method, rendor() is not a method of React.Component.
Kyle is right and also you want to call render() and not rendor(). This component is also probably better written as a stateless functional component, for example:
const RendorTest = (props) => {
return (
<div>
<h1>Spring Boot + Rest + React.js</h1>
</div>
)
}