Rendering new component on click in react - javascript

I'm practicing react and trying to render a new component on click of a button. Here the first page is email and the component i want to render contains password page.
class App extends React.Component {
passwordpage(){
return(
<form>
<div className="mainapp">
<h2> Password</h2>
<input type='Password' className="inputpassword" placeholder='Enter Password' required/>
<div>
<button type="submit" className="loginbutton">Next</button>
</div>
</div>
</form>
);
};
render() {
return (
<form>
<div className="mainapp">
<h2>Email Id</h2>
<input type='email' ref='enteremail'className="inputemail" placeholder='Enter Username' required/>
<div>
<button type="submit" onClick={this.props.passwordpage} className="loginbutton">Next</button>
</div>
</div>
</form>
);
}
}
ReactDOM.render(<App/>,document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>

The simplest is to have the password page already prepared in your render(),
and to show/hide it depending on the component state, that is mutated by the onClick handler, something along those lines:
showPasswordPage() {
this.setState({showPassword: true });
}
render() {
const passwordPage = (<form>
<div className="mainapp">
<h2> Password</h2>
<input type='Password' className="inputpassword" placeholder='Enter Password' required/>
<div>
<button type="submit" className="loginbutton">Next</button>
</div>
</div>
</form>);
const mainForm = (<form>
<div className="mainapp">
<h2>Email Id</h2>
<input type='email' ref='enteremail'className="inputemail" placeholder='Enter Username' required/>
<div>
<button type="submit" onClick={this.showPasswordPage} className="loginbutton">Next</button>
</div>
</div>
</form>);
return { this.state.showPassword ? passwordPage : mainForm };

I usually keep some variables in state and change them based on user action.
So in your case I have stored the current active page e.g usernamePage and when user clicks next I show another page in your case it is passwordPage.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isPasswordPage : false,
isUsernamePage : true,
username : "",
password : ""
};
this.enablePasswordPage = this.enablePasswordPage.bind(this);
}
enablePasswordPage() {
this.setState({
isPasswordPage : true,
isUsernamePage : false
});
}
passwordpage(){
return(
<form>
<div className="mainapp">
<h2> Password</h2>
<input type='Password' className="inputpassword" placeholder='Enter Password' required/>
<div>
<button type="submit" className="loginbutton">Next</button>
</div>
</div>
</form>
);
};
render() {
var usernameComp = (
<form>
<div className="mainapp">
<h2>Email Id</h2>
<input type='email' ref='enteremail'className="inputemail" placeholder='Enter Username' required/>
<div>
<button onClick={this.enablePasswordPage} className="loginbutton">Next</button>
</div>
</div>
</form>
);
return (
<div>
{ this.state.isUsernamePage ? usernameComp : null }
{ this.state.isPasswordPage ? this.passwordpage() : null }
</div>
);
}
}
ReactDOM.render(<App/>,document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>

What you need to do is to make use of react-router and then create separate components for each of the Page that you want to display. That is the best possible way to achieve what you want to do.
You components will look something like
class Home extends React.Component {
render() {
return (
<div>{this.props.children}</div>
)
}
}
class App extends React.Component {
handleClick = (e) => {
e.stopPropagation();
browserHistory.push('/passwordPage');
}
render() {
return (
<form>
<div className="mainapp">
<h2>Email Id</h2>
<input type='email' ref='enteremail'className="inputemail" placeholder='Enter Username' required/>
<div>
<button className="loginbutton" onClick={this.handleClick}>Next</button>
</div>
</div>
</form>
);
}
}
class PasswordPage extends React.Component {
render() {
return (
<form>
<div className="mainapp">
<h2> Password</h2>
<input type='Password' className="inputpassword" placeholder='Enter Password' required/>
<div>
<button type="submit" className="loginbutton">Next</button>
</div>
</div>
</form>
)
}
}
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={Home}>
<IndexRoute component={App} />
<Route path="/passwordPage" component={PasswordPage} />
</Route>
</Router>
)
Look at the react-router docs here

Related

Why is my useState not working (error in console)?

I have react components:
WelcomePage.jsx
import { useState } from "react";
import SignUpPage from "./SignUpPage";
function WelcomePage() {
const [signUp, toSignUp] = useState(false);
function signUpClick() {
toSignUp(true);
}
return (
<div>
{signUp ? (
<SignUpPage isOpen={toSignUp} back={toSignUp} />
) : (
<div className="Welcome_page__container animate__animated animate__fadeIn">
<h1 className="Welcome_page__title">Welcome to Hotel Review </h1>
<h3 className="Welcome_page__subtitle">Sign in :</h3>
<div className="Welcome_page__wrapper">
<label className="Welcome_page__input-title" htmlFor="welcome_mail">
E-mail:
</label>
<input
value={inputEmail}
onInput={(e) => setInputEmail(e.target.value)}
className="Welcome_page__input"
id="welcome_mail"
type="email"
placeholder="Your e-mail..."
/>
<label className="Welcome_page__input-title" htmlFor="welcome_pass">
Password:
</label>
<input
value={inputPass}
onInput={(e) => setInputPass(e.target.value)}
className="Welcome_page__input"
id="welcome_pass"
type="password"
placeholder="Your password..."
/>
<button className="Welcome_page__btn" onClick={loginClick}>
Login
</button>
<button className="Welcome_page__btn" onClick={signUpClick}>
Sign Up
</button>
</div>
</div>
)}
</div>
);
}
export default WelcomePage;
SignUpPage.jsx
import { useState } from "react";
import { Hotels } from "./Hotels";
function SignUpPage(props) {
const { isOpen, back } = props;
const [isSignUp, setSignUp] = useState(false);
return (
<div>
{isSignUp ? (
<Hotels />
) : (
<div className="Welcome_page__container animate__animated animate__fadeIn">
<button onClick={back(false)}>Back...</button>
<h1 className="Welcome_page__title">Welcome to Hotel Review </h1>
<h3 className="Welcome_page__subtitle">Sign up :</h3>
<div className="Welcome_page__wrapper">
<label className="Welcome_page__input-title" htmlFor="welcome_mail">
E-mail:
</label>
<input
value={inputEmail}
onInput={(e) => setInputEmail(e.target.value)}
className="Welcome_page__input"
id="welcome_mail"
type="email"
placeholder="Your e-mail..."
/>
<label className="Welcome_page__input-title" htmlFor="welcome_pass">
Password:
</label>
<input
value={inputPass}
onInput={(e) => setInputPass(e.target.value)}
className="Welcome_page__input"
id="welcome_pass"
type="password"
placeholder="Your password..."
/>
<label
className="Welcome_page__input-title"
htmlFor="welcome_pass"
></label>
<input
value={inputPass2}
onInput={(e) => setInputPass2(e.target.value)}
className="Welcome_page__input"
id="welcome_pass_repeat"
type="password"
placeholder="Repeat password..."
/>
<button className="Welcome_page__btn_2">Sign Up</button>
</div>
</div>
)}
</div>
);
}
export default SignUpPage;
When I click on Back in the SignUpPage component I get an error -
It is necessary that after clicking on back there is a return to WelcomePage.jsx
Maybe I'm not using or passing useState in SignUpPage.jsx
I read about the error on the Internet, they say that you need to useEffect (), but I doubt that this is the problem ...
Here is the error:
<button onClick={back(false)}>Back...</button>
You are basically calling the back function immediately causing the WelcomePage component to update while rendering the SignUpPage component.
You should do this:
<button onClick={() => back(false)}>Back...</button>
By doing this you are going to execute the back function only when you click on the button

Why css file of one component interacted with the css file of another component in ReactJS? How to handle it?

I am trying to make a website template with Reactjs. In the Jumbotron section i make subscription form and in the home section User Entry form. But the css of one component interacted with another's one. How can i handle it?
[1]: https://i.stack.imgur.com/Wd4OQ.png
User EntryJs:-
import React, { Component } from 'react'
import './User Entry.css'
class Form extends Component {
initialState = {
name: "",
age: "",
job: ""
}
state = this.initialState
changeHandler = event => {
const { name, value } = event.target
this.setState({
[name]: value
})
}
render() {
const { name, job, age } = this.state
return (
<form className="form-inline">
<div className="row">
<div className="col-md-3">
<div className="form-group">
<label htmlFor="name">Name:-</label>
<input type="text"
className="form-control"
name="name"
id="name"
value={name}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3">
<div className="form-group">
<label htmlFor="age">Age:-</label>
<input type="text"
className="form-control"
name="age"
id="age"
value={age}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3">
<div className="form-group">
<label htmlFor="job">Job:-</label>
<input type="text"
className="form-control"
name="job"
id="job"
value={job}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3"></div>
</div>
</form>
)
}
}
export default Form
Header JS:-
import React, { Component } from 'react'
import './Header.css'
import { Link, withRouter } from "react-router-dom";
class Header extends Component {
constructor(props) {
super(props)
this.state = {
email: ""
}
}
submitHandler = event => {
event.preventDefault();
alert(`Subscribed Email is : ${this.state.email}`);
}
changeHandler = event => {
this.setState({
email: event.target.value
})
}
render() {
return (
// Navbar Starts
<div>
<div className="row navbar">
<Link to="/" style={{textDecoration:'none'}}><div className="col-md-2 logo">ReactApp</div></Link>
<div className="col-md-6"></div>
<Link to="/" style={{textDecoration:'none'}}> <div className="col-md-1 link"> Home</div> </Link>
<Link to="/about" style={{textDecoration:'none'}}> <div className="col-md-1 link"> About</div> </Link>
<Link to="/counter" style={{textDecoration:'none'}}> <div className="col-md-1 link"> Counter </div></Link>
<Link style={{textDecoration:'none'}}><div className="col-md-1 link">Login</div></Link>
</div>
<div className="jumbotron text-center">
<h1>React-App</h1>
<p>We specialize in <strong>Web Development</strong></p>
{/* Subscribing form starts*/}
<form className="form-inline subscribingForm" onSubmit={this.submitHandler}>
<div className="input-group">
<input type="email"
className="form-control"
value={this.state.email}
onChange={this.changeHandler}
size="80"
placeholder="Email..."
required />
<div className="input-group-btn">
<input type="submit" value="Subscribe" className="subscribingBtn" />
</div>
</div>
</form>
{/* Subscribing form closes*/}
</div>
</div>
)
}
}
export default withRouter(Header);
Where is the .css file loaded, in the root component? It probably is loaded globally and is used on every component.Better use JSS (https://cssinjs.org/?v=v10.3.0)
In general react transpiles all the css and add it in to tag.
And as result you one file css conflicts with other.
If you want to avoid this, you can use modular css.
https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/

Submit login form made with React components

I am creating a login form with some input components and a button component.
SignIn.js
class SignIn extends Component {
render() {
return (
<article className="br2 ba dark-gray b--black-10 mv4 w-100 w-50-m w-30-l h-auto h-auto-l h-auto-m h-auto-m h-auto-ns shadow-5 center">
<main className="pa4 black-80">
<legend className="f2 fw6 ph0 mh0 tc">Sign In</legend>
<VerticalInputComponent id_name="signin_email" input_label="Email" />
<VerticalInputComponent id_name="signin_password" input_label="Password" />
<div className="tc mt3 mt3-l mt3-m mt3-ns">
<ButtonComponent button_value="Sign In" />
</div>
</main>
</article>
);
}
}
VerticalInputComponent.js
class VerticalInputComponent extends Component {
render() {
return(
<form className="pl4 pr4 pt4 pb2 black-80 w-100 measure">
<div className="measure">
<label htmlFor={ this.props.id_name } className="f6 b db mb2">{ this.props.input_label }
{ this.props.isOptional
? <span className="normal black-60">(optional)</span>
: null
}
</label>
<input id={ this.props.id_name } className="input-reset ba b--black-20 pa2 mb2 db w-100" type="text" aria-describedby="name-desc" />
</div>
</form>
)
}
}
ButtonComponent.js
class ButtonComponent extends Component {
render() {
return (
<div>
<input
className="b ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
type="submit"
value={ this.props.button_value }
/>
</div>
);
}
}
The question is how do I submit the email and password on a post request? I know how to do it on normal HTML but I don't know how to do it in React. I am guessing I need to use Redux or state but I don't know the syntax. The random examples that I read doesn't make sense to me at least for now.
There is no need for Redux or even a state to submit a form.
You should wrap the entire form element in a single form, even if they are nested in custom components. You had 2 forms, one for each input, but you're only wanting to send 1 signin POST request.
Also dont forget to include the name attribute in your form input elements because these are the property names the server will see in your POST request.
Note that e.preventDefault(); is to prevent the window from refreshing and we don't want that in a single-page application.
class VerticalInputComponent extends React.Component {
render() {
return(
<div className="measure">
<label htmlFor={ this.props.id_name } className="f6 b db mb2">{ this.props.input_label }
{ this.props.isOptional
? <span className="normal black-60">(optional)</span>
: null
}
</label>
<input id={ this.props.id_name } name={this.props.id_name} className="input-reset ba b--black-20 pa2 mb2 db w-100" type="text" aria-describedby="name-desc" />
</div>
)
}
}
class ButtonComponent extends React.Component {
render() {
return (
<div>
<input
className="b ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
type="submit"
value={ this.props.button_value }
/>
</div>
);
}
}
class SignIn extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const data = new FormData(e.target);
for (var pair of data.entries()) {
console.log(pair[0] + ': ' + pair[1]);
}
fetch('/someURL', {
method: 'POST',
body: data,
});
}
render() {
return (
<article className="br2 ba dark-gray b--black-10 mv4 w-100 w-50-m w-30-l h-auto h-auto-l h-auto-m h-auto-m h-auto-ns shadow-5 center">
<main className="pa4 black-80">
<legend className="f2 fw6 ph0 mh0 tc">Sign In</legend>
<form onSubmit={this.handleSubmit}>
<VerticalInputComponent id_name="signin_email" input_label="Email" />
<VerticalInputComponent id_name="signin_password" input_label="Password" />
<div className="tc mt3 mt3-l mt3-m mt3-ns">
<ButtonComponent button_value="Sign In" />
</div>
</form>
</main>
</article>
);
}
}
// Render it
ReactDOM.render(
<SignIn/>,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Toggle element isHidden True/False with React

I have a problem with this code, my Toggle button doesn't display the Child element but gives me a full blank page
Here is the code
class App extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {items: [] , isHidden: true};
this.toggleHidden = this.toggleHidden.bind(this);
}
componentDidMount() {
fetch("/customers")
.then(result=>result.json())
.then(items=>this.setState({items}));
}
toggleHidden () {
this.setState({
isHidden: !this.state.isHidden
});
}
render() {
return (
<div id='customerDetails'>
{this.state.items.map(item=><customerDetail>
<div id={item._id} >
<button onClick={this.toggleHidden} data-arg1={item._id} value='U'/>
{item.cost}
{!this.state.isHidden && <Child >
<div className='modal'>
<form onSubmit={this._handleUpdate}>
<input type='text' id='cost' name='cost'/>
<input type='hidden' id="_id" name='_id' value=item.id />
<input type='submit' value='Update'/>
</form>
</div>
</Child>
}
</div>
</customerDetail>)}
</div>
);
}
}
Any idea , i do not know if it's coming from the fact all that happens in an iteration
I also tried this standalone source code from StackOverflow React toggle component that should work, and it does not work....blank page
Any idea
Thanks
Firstly you need fix errors in the code.
Change line <input type='hidden' id="_id" name='_id' value=item.id /> to <input type='hidden' id="_id" name='_id' value={item.id} />
i just tried this in my parent component render function:
<button onClick={this.toggleHidden} value='U'/>
{item.cost}
{!this.state.isHidden && <Child />}
and on the bottom of the code i add a Child class:
class Child extends React.Component {
render() {
return (
<div className='modal'>
<form >
<input type='text' id='cost' name='cost'/>
<input type='hidden' id="_id" name='_id' />
<input type='submit' value='Update'/>
</form>
</div>
)
}
}
But i have stil a blank page when toggle
I made my code work, here it is :
Remove Child component at the bottom of the page
Add a function CHild at the beginning :
function Child(props) {
return (
<div className='modal'>
<form onSubmit={props.onClick}>
<input type='text' id='cost' name='cost'/>
<input type='hidden' id="_id" name='_id' value={props.value} />
<input type='submit' value='Update'/>
</form>
</div>
);
}
Added the function renderChild in my parent component :
renderChild(i) {
return (
<Child
value={i}
onClick={() => this.props.onClick(i)}
/>
);
}
Finally in the render of my parent component , replace the line :
{!this.state.isHidden && <Child/>}
by
{!this.state.isHidden && this.renderChild(item._id)}
Now my toggle function works

Keep code DRY on create/edit form

I have a few inputs that are used in my form for both create and update. I decided to make them a component.
// used for CRU on the event record
import React from 'react';
class Form extends React.Component {
render() {
return (
<div className="slds-form">
<div className="slds-form-element">
<label className="slds-form-element__label">Assigned To</label>
<div className="slds-form-element__control">
<input ref={(input) => this.assigned = input} type="text" className="slds-input" disabled/>
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Related To</label>
<div className="slds-form-element__control">
<input ref={(input) => this.related = input} type="text" className="slds-input" disabled/>
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Location</label>
<div className="slds-form-element__control">
<input ref={(input) => this.location = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Event Start</label>
<div className="slds-form-element__control">
<input ref={(input) => this.start = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Event End</label>
<div className="slds-form-element__control">
<input ref={(input) => this.end = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Contact</label>
<div className="slds-form-element__control">
<input ref={(input) => this.contact = input} type="text" className="slds-input" disabled/>
</div>
</div>
<button type="button" className="slds-button slds-button--neutral">Cancel</button>
<button type="submit" className="slds-button slds-button--brand">{this.props.buttonLabel}</button>
</div>
);
}
}
export default Form;
I then attempted to use this component in my <Create /> component.
// used for Create on the event record
import React from 'react';
import Form from './Form';
class Create extends React.Component {
createEvent(e) {
console.log("createEvent() has fired.");
e.preventDefault();
const event = {
assigned: this.assigned.value,
related: this.related.value,
location: this.location.value,
start: this.start.value,
end: this.end.value,
contact: this.contact.value
}
console.log(event);
}
render() {
return (
<form onSubmit={(e) => this.createEvent(e)}>
<Form buttonLabel="Create" />
</form>
);
}
}
export default Create;
When I try to hit the Create button on my <Create /> component I get an error
Uncaught TypeError: Cannot read property 'value' of undefined
at Create.createEvent (webpack:///./src/components/Event/Create.js?:42:32)
at onSubmit (webpack:///./src/components/Event/Create.js?:59:27)
at Object.ReactErrorUtils.invokeGuardedCallback (webpack:///./~/react/lib/ReactErrorUtils.js?:70:16)
at executeDispatch (webpack:///./~/react/lib/EventPluginUtils.js?:89:21)
at Object.executeDispatchesInOrder (webpack:///./~/react/lib/EventPluginUtils.js?:112:5)
at executeDispatchesAndRelease (webpack:///./~/react/lib/EventPluginHub.js?:44:22)
at executeDispatchesAndReleaseTopLevel (webpack:///./~/react/lib/EventPluginHub.js?:55:10)
at Array.forEach (native)
at forEachAccumulated (webpack:///./~/react/lib/forEachAccumulated.js?:25:9)
at Object.processEventQueue (webpack:///./~/react/lib/EventPluginHub.js?:231:7)
I then check the console and see the refs belong in my <Form /> component, and not my <Create /> component.
Is there a way to pass the refs from my child component, <Form />, to its parent, <Create />?
That's a lot of refs! Good news, you really don't need them, at all. As a very very general rule, you should only be using refs if you are interacting with an external library that doesn't "understand" React (d3, Greensock, TinyMCE, etc).
Tackling it in an uncontrolled way can be done like:
const User = (props) => (
<div>
<input name="foo" className="form-control" />
<input name="foo2" className="form-control" />
<button type="submit" className="btn btn-primary">{props.buttonLabel}</button>
</div>
);
class App extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
onSubmit(e) {
e.preventDefault();
console.log(this.state);
}
render() {
return (
<div className="container">
<br />
<form onChange={this.onChange} onSubmit={this.onSubmit}>
<User buttonLabel="Create"/>
</form>
</div>
);
}
};
ReactDOM.render(<App />, document.getElementById('app'));
Codepen example:
http://codepen.io/cjke/pen/zNXxga?editors=0010

Categories

Resources