I'm building an app with React and I'm trying to implement a modal appearing after error occurring.
This is a simply login card with input boxes and I do a post request to login or sign-up new users.
If there's any error in my form or users already exists I want to popup a modal with error messages like the following.
I can't understand why it isn't showing. The error is ok and the backdrop is visible. Any help is appreciated.
There's my code:
This is the JSX code:
import { useHttpClient } from '../hooks/http-hook';
const { isLoading, error, sendRequest, clearError } = useHttpClient();
...
return (
<React.Fragment>
<ErrorModal error={error} onClear={clearError} />
<div className="container">
{isLoading && <LoadingSpinner asOverlay />}
<div className="card card-container">
<img id="profile-img" className="profile-img-card" alt="Login Avatar" src={require("../../assets/images/avatar.png")} />
<p id="profile-name" className="profile-name-card"></p>
<form className="form-signin" onSubmit={loginSubmitHandler}>
<span id="reauth-email" className="reauth-email"></span>
{!isLoginMode && (
<Input
element="input"
id="username"
type="text"
title="Username"
placeholder="USERNAME"
validators={[VALIDATOR_REQUIRE()]}
errorText="Required."
onInput={inputHandler}
/>
)}
<Input
element="input"
id="email"
type="text"
title="EMAIL"
placeholder="EMAIL"
validators={[VALIDATOR_EMAIL()]}
errorText="Invalid email address."
onInput={inputHandler}
/>
<Input
element="input"
id="password"
type="password"
title="PASSWORD"
placeholder="PASSWORD"
validators={[VALIDATOR_MINLENGTH(5)]}
errorText="Your password must have at least 5 characters."
onInput={inputHandler}
/>
<Button type="submit" disabled={!formState.isValid}>
{isLoginMode ? 'LOGIN' : 'SIGNUP'}
</Button>
</form>
<Button inverse onClick={switchModeHandler}>
SWITCH TO {isLoginMode ? 'SIGNUP' : 'LOGIN'}
</Button>
</div>
</div>
</React.Fragment>
)
This is my Modal.js
import React from 'react';
import ReactDOM from 'react-dom';
import { CSSTransition } from 'react-transition-group';
import Backdrop from './Backdrop';
import './Modal.css';
const ModalOverlay = props => {
const content = (
<div className={`modal ${props.className}`} style={props.style}>
<header className={`modal__header ${props.headerClass}`}>
<h2>{props.header}</h2>
</header>
<form
onSubmit={
props.onSubmit ? props.onSubmit : event => event.preventDefault()
}
>
<div className={`modal__content ${props.contentClass}`}>
{props.children}
</div>
<footer className={`modal__footer ${props.footerClass}`}>
{props.footer}
</footer>
</form>
</div>
);
return ReactDOM.createPortal(content, document.getElementById('modal-hook'));
};
const Modal = props => {
return (
<React.Fragment>
{props.show && <Backdrop onClick={props.onCancel} />}
<CSSTransition
in={props.show}
mountOnEnter
unmountOnExit
timeout={200}
classNames="modal"
>
<ModalOverlay {...props} />
</CSSTransition>
</React.Fragment>
);
};
export default Modal;
And this my ErrorModal.js
import React from 'react';
import Modal from './Modal';
import Button from '../formElements/Button';
const ErrorModal = props => {
return (
<Modal
onCancel={props.onClear}
header="An Error Occurred!"
show={!!props.error}
footer={<Button onClick={props.onClear}>Okay</Button>}
>
<p>{props.error}</p>
</Modal>
);
};
export default ErrorModal;
It was simply my bootstrap.css to create a mess.....
<link rel="stylesheet" href="%PUBLIC_URL%/stylesheets/bootstrap/bootstrap.css">
I simply renamed the modal class in custom_modal
Related
I want to create a login page. When the user submits the form, the username should be rendered on the dashboard. I am unable to figure that out.
import React from "react";
import Footer from "./Footer";
import Back from "./Back";
import { Link } from "react-router-dom";
const Login = () => {
return (
<div>
<Back />
<div>
<form className="login-form">
<h1 className="form-heading">Login</h1>
<input
className="form-input"
type="text"
placeholder="Enter your Username"
/>
<input
className="form-input"
type="password"
placeholder="Enter your password"
/>
<button className="form-button">
<Link to={"/dashboard"}>Login</Link>
</button>
</form>
</div>
<Footer />
</div>
);
};
export default Login;
To share data between two components, the standard react approach is to lift the state up to a parent component, then pass it down (through props or context). For example:
const App = () => {
const [user, setUser] = useState();
return (
<Routes>
<Route path="/login" element={<Login setUser={setUser}/>}
<Route path="/dashboard" element={<Dashboard user={user}/>}
</Routes>
)
}
const Login = ({ setUser }) => {
return (
// ...
<Link to="/dashboard" onClick={() => setUser('bob')}
// ...
);
}
const Dashboard = ({ user }) => {
return (
<div>
Hello {user}!
</div>
)
}
I'm trying to render a functional component. But for some reason, I'm getting this sentence on the console You need to enable JavaScript to run this app.
This is App.js
import './App.css';
import Home from './components/pages/home/Home';
import SignUp from './components/pages/sign/SignUp';
import Checking from './components/pages/sign/Checking';
import Login from './components/pages/sign/Login';
import Summery from './components/pages/summery/Summery';
import UserList from './components/pages/users/Users';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import UploadFiles from './components/pages/files/UploadFiles';
function App() {
return (
<Router>
<Routes>
<Route exact path='/' element= {<Home />}/>
<Route path='/sign-up' component= {Checking } />
<Route path='/log-in' element= {<Login />} />
<Route path='/admin' element= {<Summery />} />
<Route path='/users' element= {<UserList />} />
<Route path='/files' element= {<UploadFiles />} />
</Routes>
</Router>
);
}
export default App;
Home, Login, Summery, UserList and UploadFiles are React Components and not functions.
Only Checking is a function (Trying to convert everything to a function component).
They all render but only Checking logging into console You need to enable JavaScript to run this app.
This is Checking.js file
import React from "react";
import '../../../App.css';
import Button from '#material-ui/core/Button';
import SendIcon from '#material-ui/icons/Send';
import axios from 'axios';
import bcrypt from 'bcryptjs';
import Navbar from "../../navbar/Navbar";
import { useNavigate } from 'react-router-dom';
export default function Checking() {
const [companyID, setCompanyID] = React.useState('');
const [email, setEmail] = React.useState('');
const navigate = useNavigate();
function handleSubmit(Event) {
Event.preventDefault();
axios.post('/sign-up', {
companyID: companyID,
email: email})
.then(res =>{
//console.log(res.json());
console.log(res);
if(res.status === 200){
//this.app();
//history.push('/login');
}else if (res.status === 400){
console.log("duplicate ID");
}
}).catch(err =>{
// console.log("duplicate ID");
// console.log(err);
});
}
}
return (
<>
<Navbar />
<div className="register-container" ref={this.props.containerRef}>
<h1 className="sign-up">SIGN UP</h1>
<form onSubmit={handleSubmit}>
<div className="form">
<div className="form-group">
{/* <label htmlFor="company id">Company ID : </label> */}
<input
type="number"
name="companyID"
placeholder="Company id"
value={companyID}
onChange={(e) => setCompanyID(e.target.value)}
required/>
</div>
{ <div className="form-group">
{/* <label htmlFor="email">Email : </label> */}
<input
type="text"
name="email" placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required/>
</div> }
<div className="registerbtn">
{/* <button type="submit" class="btn btn-primary">Submit</button> */}
<Button type="submit" endIcon={<SendIcon />} color="primary" variant="contained">
Sign Up
</Button>
</div>
</div>
</form>
</div>
</>
);
}
What am I doing wrong?
Checking is also a react component and you need to render it like the others.
<Route path='/sign-up' element= {<Checking/> } />
EDIT: Events are not working at all, the onSubmit and onChange functions are not being called. I have another reactapp with similar form and onChange and onSubmit works OK there.
I have a form I dont want the page to refresh when I click on submit. I tried using preventDefault() but I didnt work. Even onChange is printing anything on console. This form is not on page, I am using React Router to point to='/new' and component={NewPost} (NewPost is in ./components/posts/form)
./components/posts/form.js:
import React, { Component } from "react";
import { connect } from "react-redux";
class NewPost extends Component {
state = {
title: "",
body: "",
status: 0,
};
onSubmit = (e) => {
e.preventDefault();
const post = e;
console.log(post);
};
onChange = (e) => {
console.log(e.target.value);
this.setState({
[e.target.name]: e.target.value,
});
};
render() {
const { title, body, status } = this.state;
return (
<div className="card card-body mt-4 mb-4">
<h2>New Post</h2>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Title</label>
<input
type="text"
name="title"
value={title}
onChange={this.onChange}
className="form-control"
/>
</div>
<div className="form-group">
<label>Content</label>
<textarea
type="text"
name="body"
rows="15"
value={body}
onChange={this.onChange}
className="form-control"
/>
</div>
<div className="form-group">
<button className="btn btn-primary" type="submit">
Submit
</button>
</div>
</form>
</div>
);
}
}
export default NewPost;
App.js:
import React from "react";
import NavBar from "./components/layout/navbar";
import store from "./store";
import { Provider } from "react-redux";
import Dashboard from "./components/posts/dashboard";
import NewPost from "./components/posts/form";
import {
HashRouter as Router,
Route,
Switch,
Redirect,
} from "react-router-dom";
class App extends React.Component {
render() {
return (
<Provider store={store}>
<Router>
<React.Fragment>
<div className="container">
<NavBar />
<Switch>
<Route exact path="/" component={Dashboard}></Route>
<Route exact path="/new" component={NewPost}></Route>
</Switch>
</div>
</React.Fragment>
</Router>
</Provider>
);
}
}
export default App;
Issue is not related to code. I created new react application and moved all my code now everything is working fine.
I´m learning in react and practicing making a simple application to login and view messages sent.
I´ve read a lot about routing, links and redirect, but i couldn´t translate to my app.
I Would like to click in the "Login" button of a component and redirect to another component.
Here i have the principal component : App.js
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
class Login extends Component {
state = {
loggedIn:false
};
loginHandle = () => {
this.setState({loggedIn:true});
}
render(){
return (
<div className="container d-flex h-100">
<div className="row align-self-center w-100">
<div className="col-6 mx-auto">
<div className="jumbotron">
<form name="form1">
<fieldset>
<legend>Chat App</legend>
<label for="UserName" className="col-form-label">Username</label>
<input type="text" className="form-control col-12" id="UserName"></input>
<label for="Password" className="col-form-label">Password</label>
<input type="text" className="form-control col-12" id="Password"></input>
<button type="button" value="log in" className="btn btn-secondary" onClick={this.loginHandle}>Login</button>
</fieldset>
</form>
<div style={{float:"right"}}>
<div className="login-help ">
Register - Forgot Password
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Login;
I wrapped all the Links in a Navigation component
So, when i route /, it goes to the Login component
class Login extends Component {
state = {
loggedIn:false
};
loginHandle = () => {
this.setState({loggedIn:true});
}
render(){
return (
<div className="container d-flex h-100">
<div className="row align-self-center w-100">
<div className="col-6 mx-auto">
<div className="jumbotron">
<form name="form1">
<fieldset>
<legend>Chat App</legend>
<label for="UserName" className="col-form-label">Username</label>
<input type="text" className="form-control col-12" id="UserName"></input>
<label for="Password" className="col-form-label">Password</label>
<input type="text" className="form-control col-12" id="Password"></input>
<button type="button" value="log in" className="btn btn-secondary" onClick={this.loginHandle}>Login</button>
</fieldset>
</form>
<div style={{float:"right"}}>
<div className="login-help ">
Register - Forgot Password
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Login;
Do i have to import routes and redirect in the Login component, or i have to mange all from the App component?
Sorry about this mess, but i don´t know how to continue
Thanks a lot. I really apreciatted in advance.
The simplest way for navigating to another route.
For example you can wrap your Forgot password like following:
<Link to="/forgotRoute">Forgot password?</Link>
Don't forget to add /forgotRoute handling into your Navigator config (where you routed / to your Login component).
Hope it helps.
The correct way for what you want i think it is. So follow me..
You need to use router. In my case i'm using react-router-dom.
First router App component, by default page its renders DefaultPage components and in DefaultPage when component mounted you can render client anywhere.
index.js looks like:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Route, Switch } from 'react-router-dom';
class DefaultPage extends Component {
state = {
autorized: false,
mounted: false,
}
componentDidMount = () => {
const { autorized } = this.state;
if (!autorized) {
this.props.history.push('/login');
return;
}
this.setState({
mounted: true,
});
}
render = () => {
if (!this.state.mounted) {
return (
<React.Fragment>
<p>Waiting...</p>
</React.Fragment>
)
}
return (
<React.Fragment>
<p>Hello...</p>
</React.Fragment>
)
}
}
class Login extends React.Component {
handleLogin = () => {
if (contidion) {
this.props.history.push('/');
}
}
render = () {
return (
<button onClick={this.handleLogin}>Click to login</button>
)
}
}
class App extends React.Component {
render = () {
return (
<Switch>
<Route exact path="/" component={DefaultPage} />
<Route path="/login" component={Login} />
<Route component={DefaultPage} />
</Switch>
)
}
}
ReactDOM.render(
<BrowserRouter >
<App />
</BrowserRouter>,
document.getElementById("root")
);
I have a simple Redux Form and tried to follow the example given here https://redux-form.com/6.2.0/docs/GettingStarted.md/ here is my code
user-form.js
import React from 'react';
import {Field, reduxForm} from 'redux-form';
class UserForm extends React.Component {
/**
* User Form goes here...
*/
render() {
const { handleSubmit } = this.props;
return (
<form role="form" onSubmit={handleSubmit}>
<div className="box-body">
<div className="form-group">
<label htmlFor="name">Full Name</label>
<Field
name="name"
component="input"
type="text"
className="form-control"
placeholder="Enter full name..."/>
</div>
<div className="form-group">
<label htmlFor="email">Email address</label>
<Field
name="email"
type="email"
component="input"
className="form-control"
placeholder="Enter email"/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<Field
name="password"
type="password"
component="input"
className="form-control"
placeholder="Password"/>
</div>
</div>
<div className="box-footer">
{/* <button type="submit" className="btn btn-primary">Save</button> */}
<button type="submit" className="btn btn-primary" value="Save">Save</button>
</div>
</form>
);
}
}
UserForm = reduxForm({
form: 'user'
})(UserForm);
export default UserForm;
Above Form is rendered by a UserPage Container
user-page.js
import React from 'react';
import Page from '../../page';
import UserForm from '../components/user-form';
import UserList from '../components/user-list';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import UserAction from '../actions';
import {showLoading, hideLoading} from 'react-redux-loading-bar';
/**
* We might want to create an Abstract Form component to
* include all common form features.
*/
class UserPage extends Page {
handleUserSubmit(values) {
console.log(values);
}
/**
* Content is loaded into page
*/
content() {
return (
<div className="row">
{/* left column */}
<div className="col-md-6">
{/* general form elements */}
<div className="box box-primary">
<div className="box-header with-border">
<h3 className="box-title">New User</h3>
</div>
{/* /.box-header */}
<UserForm onSubmit={this.handleUserSubmit}/>
</div>
{/* /.box */}
</div>
{/*/.col (left) */}
{/* right column */}
<div className="col-md-6">
{/* UserList made of <User /> */}
{this.userList()}
{/* /.box */}
</div>
{/*/.col (right) */}
</div>
);
}
}
const mapStateToProps = (state) => ({ //this gets state from reducer and maps to props
users: state.userList.users,
fetched: state.userList.fetched,
error: state.userList.error
});
const mapDispatchToProps = (dispatch) => ({
actions: bindActionCreators({
dispatchShowLoading: showLoading,
dispatchHideLoading: hideLoading,
dispatchUserList: UserAction.userList
}, dispatch)
});
export default connect(mapStateToProps, mapDispatchToProps)(UserPage);
My Form successfully renders and I can see all the actions being dispatched inside the Redux Dev tools window, but when I try to enter text into the fields it won't do any thing, however the actions are dispatched like I said.
Sorry if this sounds a very basic question. I am relatively new to React and Redux and for that matter to Javascript.
In order to make redux form work, its reducer needs to be included and I forgot to include one, this fixed my issue.
import { reducer as formReducer } from 'redux-form';
const allReducers = combineReducers({
form: formReducer,
});
export default allReducers;