React Create simple form [duplicate] - reactjs

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.

Related

React test fails becasue target container is not a DOM element

I'm trying to run component tests and the tester keeps on failing because the target container is not a DOM element. I found an answer that recommended removing exported values from index.tsx but it did not fix the issue.
src/Component/__tests__/FirstPage.test.tsx
● Test suite failed to run
Target container is not a DOM element.
8 | export const socket = io('http://localhost:8080');
9 |
> 10 | ReactDOM.render(
| ^
11 | <React.StrictMode>
12 | <App/>
13 | </React.StrictMode>,
at Object.render (node_modules/react-dom/cjs/react-dom.development.js:26091:13)
Here is my App.tsx file
import React, { Component } from "react";
import './App.css';
import FirstPage from './Component/FirstPage/FirstPage';
export default class App extends Component {
render() {
return (
<FirstPage/>
);
}
}
Here is the index.tsx file:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import io from 'socket.io-client';
import App from './App';
import reportWebVitals from './reportWebVitals';
export const socket = io('http://localhost:8080');
ReactDOM.render(
<React.StrictMode>
<App/>
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint
reportWebVitals();
And here is the test
import { render, screen } from '#testing-library/react';
import userEvent from '#testing-library/user-event';
import React from 'react';
import FirstPage from '../FirstPage/FirstPage';
import User from '../User/User';
const testUser = new User("testUser", "id")
test('Test if FirstPage includes enter lobby button', () => {
render(<FirstPage/>);
const textElement= screen.getByText(/Enter Lobby!s/i);
expect(textElement).toBeInTheDocument();
});
Here is my index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"/>
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000"/>
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
Edit
After spending some time on your project I found out what was causing this issue with your tests. In some of the components that FirstPage is using, you were importing socket like that
import { socket } from "../.."
This caused unexpected behaviour in the tests because the path was wrong.
To fix this, I took the socket export from index.tsx and put it in App.tsx and wherever you need to import it you can just do lit like this
import { socket } from "../../App"
That resolves the issues with the tests. Also, the improvements mention above still apply for cleaner code .
First of all, in your App.tsx you are importing FirstPage and name it as Greeting but then you are returning FirstPage in your component. You need to either return Greeting or rename the import to FirstPage. Also, you need to import React in order for the code to work. Even if you don't use React explicitly, you still need to import it because JSX is tranpiled to React.createElement() which uses React.
// App.tsx
import React, { Component } from "react";
import FirstPage from "./Component/FirstPage/FirstPage";
export default class App extends Component {
render() {
return <FirstPage />;
}
}
Moving on to your test, it's a good practice to put all the tests inside __tests__ folder. Also, it looks like you don't actually import FirstPage as well and then try to use it. Try importing it and running the tests again with the proposed changes in the App.tsx.
// /Components/FirstPage/__tests__/FirstPage.test.tsx
import React from "react";
import { render, screen } from "#testing-library/react";
import FirstPage from '../FirstPage';
test("Test if FirstPage includes enter lobby button", () => {
render(<FirstPage />);
...
});
I've tried it in the codesandbox and the tests worked.

React: why set the document title inside useEffect?

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.

ReactJS ReactDOM Render for Separate Pages

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.

React Component not starting up on the project

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!

Basic react component not rendering

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>
)
}

Resources