I made a simple form and after I hit the submit button of the form, I want it to automatically redirect to a "thankyou" page I have set up. Can anyone help me solve this.
Currently, this is how I think it might work, but it keeps popping up errors.
Thank you very much.
const handleSubmit = event => {
alert("Thank you for registering ");
event.preventDefault();
event.stopPropagation();
handleClose();
redirectToPage();
};
const redirectToPage = () => redirect(true);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
if (redirect) {
return <Link to="/thankyou" />
}
return (
<>
<div className="StudentForm">
<Modal show={show} onHide={handleClose} animation={true}>
<Modal.Header closeButton>
<Modal.Title>Student Information</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form onSubmit={handleSubmit}>
<Row>
<Col>
<Form.Group controlId="std_name">
<Form.Control required type="text" id="std_name" name="std_name"
placeholder="Student Name" />
</Form.Group>
</Col>
</Row>
<Button variant="secondary" onClick={event => window.location.href='/home'}>Cancel</Button>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</Modal.Body>
</Modal>
</div>
</>
);
you wanna use Redirect from react-router-dom and i would suggest using useState hook to maintain a state variable which would determine when to redirect and in redirectToPage you would just set it to true
import React,{Fragment,useState} from "react";
import { Redirect } from "react-router-dom";
const [redirect, setRedirect] = useState(false);
const redirectToPage = () => setRedirect(true) ;
return (
{redirect && (
<Fragment>
<Redirect to='/thankyou' />
</Fragment>
)}
<div className="StudentForm">
// Rest of Code
);
Related
I am looking to send the value from the Form.Control to the button so I can do some logic but I cannot seem to get this value from the input. I tried using reft but I cant use refs in a functional component, so I'm using the textInput. Please help, been stuck for 3 days. thx
import React from "react";
import { Modal, Form, Row, Col, Button } from "react-bootstrap";
import "./Login.css";
export const ForgotPassword = (props) => {
let textInput = null;
const handleClick = () => {
console.log("i am here", textInput.focus());
};
return (
<>
<Modal
{...props}
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
Forgot Password
</Modal.Title>
</Modal.Header>
<Modal.Body className="show-grid">
<Form.Label>Please enter your Employee ID.</Form.Label>
<Row>
<Col className="lm-qus" md={5}>
Employee ID:
</Col>
<Col md={7}>
<Form.Control
type="text"
required
name="answer"
placeholder=""
ref={(input) => {
textInput = input;
}}
/>
</Col>
</Row>
</Modal.Body>
<Modal.Footer>
<Button onClick={props.onHide}>Cancel</Button>
<Button onClick={handleClick} type="submit">
Continue
</Button>
</Modal.Footer>
</Modal>
</>
);
};
This is not a modal specific problem. Make your Form.Control a controlled input by providing "value" attribute. Define state and set this state on change event of the input. You can then access this state everywhere, including the button:
const [value, setValue] = React.useState("");
const handleChange = (event) => setValue(event.target.value);
const handleClick = () => alert(value);
https://codesandbox.io/s/objective-pond-rs8r9f
I am utilizing react bootstrap and firebase to create a Modal to allow signIn - I have a create user component fully implemented but when I try to use a modal to handle my sign in it error out . Any help is much appreciated.
Uncaught (in promise) TypeError: Cannot destructure property 'email' of 'event.target.elements' as it is undefined.
import React, { useState, useCallback, useContext } from 'react';
import './Homepage.css';
import { Button, Modal, Form } from 'react-bootstrap';
import { Link, Redirect } from 'react-router-dom';
// Firebase Credentials
import app from '../firebase'
import { AuthContext } from '../Auth'
const Homepage = ({ history }) => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const handleLogin = useCallback(
async (event)=> {
event.preventDefault();
const { email, password } = event.target.elements;
try {
await app.auth().signInWithEmailAndPassword(email.value, password.value);
history.push('/generate')
}catch(error){
alert(error);
}
},[history]
);
const { currentUser } = useContext(AuthContext);
if (currentUser) {
return
}
return (
<div className='welcomeContainer'>
<h1 className='welcomeBanner'>Resu.Me</h1>
<h4 className='welcomeMessage'>
Resu.me is the easiest solution for cover letters and resumes.
<br></br> Simply input your credentials and contact information - We
handle the rest!
</h4>
<Link className='genLeadButton' to='/generate'>
<Button>Let's make a Resume</Button>
</Link>
<Button onClick={handleShow} className='loginButton'>
Log In to Resu.me
</Button>
{/* <h2 className="servicesBanner">Score the job you deserve with the help of our tools</h2> */}
<h2 className='servicesContainer serviceA'>PLACEHOLDER A</h2>
<h2 className='servicesContainer serviceB'>PLACEHOLDER B</h2>
<h2 className='servicesContainer serviceC'>PLACEHOLDER C</h2>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Login</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId='formBasicEmail'>
<Form.Label className='label'>Email Address</Form.Label>
<Form.Control
name='email'
type='email'
placeholder="Login email"
/>
</Form.Group>
<br></br>
<Form.Group controlId='formBasicPassword'>
<Form.Label>Password</Form.Label>
<Form.Control
name='password'
type='password'
placeholder='Password'
/>
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button variant='secondary' type='submit' onClick={handleLogin}>
Login
</Button>
</Modal.Footer>
</Modal>
</div>
);
};
export default Homepage;
const { email, password } = event.target.elements;
will map the value by the input id (controlId for react-bootstrap forms) in these two rows
<Form.Group controlId='formBasicEmail'>
<Form.Group controlId='formBasicPassword'>
so you have to make them identical like:
const { formBasicEmail, formBasicPassword } = event.target.elements;
or
<Form.Group controlId='email'>
<Form.Group controlId='password'>
In a React project, I have the requirement of opening Modal from another component. I found suggested questions from StackOverflow but, not yet convinced. As I need to make the Modal component reusable across all components. See the code below for reference
Homepage.js
const HomePage = () => {
return (
<>
<button onClick={() => setLoginModalShow(true)}>Open Modal</button>
</>
);
};
I created the below file to export other files too, and make it useful in other components
commonLogin.js
import LoginModal from "./LoginModal";
export const setLoginModalShow = (props) => {
console.log("PROPS", props);
return <LoginModal showModal={props} />;
};
And here is the Modal component
const LoginModal = (props) => {
const [loginModalShow, setLoginModalShow] = useState(props.showModal);
console.log("PROPS in MODAL", props);
return (
<>
<Modal
show={loginModalShow}
onHide={setLoginModalShow}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">Logout</Modal.Title>
</Modal.Header>
<Modal.Body>
<h4>Are you sure to Logout?</h4>
</Modal.Body>
<Modal.Footer>
<Button onClick={() => setLoginModalShow(false)}>Cancel</Button>
</Modal.Footer>
</Modal>
</>
);
};
Please refer to the code sandbox link: https://codesandbox.io/s/nameless-cdn-70zuq.
After you visit the page click on the 'Open Modal' button
You want to control the show/hide from the parent component
const HomePage = () => {
const [showLogin, setShowLogin] = useState(false);
return (
<>
<button onClick={() => setShowLogin(true)}>Open Modal</button>
<LoginModal show={showLogin} close={() => setShowLogin(false)} />
</>
);
};
<Modal
show={props.show}
cancel={props.close}
...
Here is a working example:
https://codesandbox.io/s/nice-euclid-d0dw0
Whenever I try to render my component, I am getting this error :
too many re-renders. react limits the number of renders to prevent an
infinite loop.
I have tried using axios cancelToken and square brackets in useEffect hook. But nothing works. The code requests an array of notifications from server and store it in a state variable "notifications", using useState react hook. Here's my code:
import React, {useState, useEffect} from 'react';
import NavbarComponent from './NavbarComponent';
import { Card, Button, Modal } from "react-bootstrap";
import axios from 'axios';
function Notifications({username}) {
const [show, setShow] = useState(false);
const [response, setresponse] = useState([])
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const [notifications, setnotifictions] = useState([])
const [password, setpassword] = useState("")
var user = {
username: username
}
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
useEffect(() => {
const fetchnoti = async () => {
await axios.post('/api/getnoti', user, {cancelToken: source.token})
.then(res => {
console.log(res)
setnotifictions(res.data)
})
.catch(err => {
if (axios.isCancel(err)) {
console.log('Request canceled', err.message);
}
else console.log(err)
})
}
fetchnoti();
return () => {
source.cancel()
}
}, [])
function accept(noti){
var param = {
noti: noti,
password: password
}
axios.post('/api/accepttxn', param)
.then(res => {
console.log(res)
setresponse(res.data)
})
.catch(err => {
console.log(err)
})
}
function accepttxn(noti){
handleShow();
setresponse([]);
setpassword("");
return(
<div>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Enter Password to Proceed</Modal.Title>
</Modal.Header>
<Modal.Body><input type="password" value={password} onChange={(event) => setpassword(event.target.value)}/></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="success" onClick={() => {accept(noti)}}>
Proceed to Accept
</Button>
{response}
</Modal.Footer>
</Modal>
</div>
);
}
function reject(noti){
var param = {
noti: noti,
password: password
}
axios.post('/api/rejecttxn', param)
.then(res => {
console.log(res)
setresponse(res.data)
})
.catch(err => {
console.log(err)
})
}
function rejecttxn(noti){
handleShow();
setresponse([]);
setpassword("");
return(
<div>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Enter Password to Proceed</Modal.Title>
</Modal.Header>
<Modal.Body><input type="password" value={password} onChange={(event) => setpassword(event.target.value)}/></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="danger" onClick={() => {reject(noti)}}>
Proceed to Reject
</Button>
{response}
</Modal.Footer>
</Modal>
</div>
);
}
const notis = notifications.map((noti) => {
return(
<Card key={noti.id}>
<Card.Body>
<Card.Text>
Sender: {noti.sender}
</Card.Text>
<Card.Text>
Amount: {noti.amount}
</Card.Text>
<Card.Text>
{noti.message ? <div>Message: {noti.message}</div> : null}
</Card.Text>
<Button variant="primary"
onClick={
accepttxn(noti)
}>Accept</Button>
<Button variant="danger"
onClick={
rejecttxn(noti)
}>Reject</Button>
</Card.Body>
</Card>
)
})
return (
<div>
{notis.length ? <div>{notis}</div> : <h1>No new notifications</h1>}
</div>
);
}
export default Notifications;
Can anyone help me out?
It's not the useEffect probably, you have a button which calls a function whenever it renders:
<Button variant="danger" onClick={rejecttxn(noti)}>Reject</Button>
You could rewrite the function to return a function, it improves performance because you may re-render components that does not need to be rerendered when using inline functions, check below example:
function rejecttxn(noti){
return function() {
handleShow();
setresponse([]);
setpassword("");
return (
<div>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Enter Password to Proceed</Modal.Title>
</Modal.Header>
<Modal.Body><input type="password" value={password} onChange={(event) => setpassword(event.target.value)}/></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="danger" onClick={() => {reject(noti)}}>
Proceed to Reject
</Button>
{response}
</Modal.Footer>
</Modal>
</div>
);
}
}
Or using arrow functions:
const rejecttxn = (noti) => () => {
handleShow();
setresponse([]);
setpassword("");
return (
<div>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Enter Password to Proceed</Modal.Title>
</Modal.Header>
<Modal.Body><input type="password" value={password} onChange={(event) => setpassword(event.target.value)}/></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="danger" onClick={() => {reject(noti)}}>
Proceed to Reject
</Button>
{response}
</Modal.Footer>
</Modal>
</div>
);
}
}
I tried asking a question earlier but realized it was a bit all over the place so no one could really understand it properly. So here's a more clarified attempt.
I am currently working on a CRUD web project that allows the user to edit, view and create more users which is then displayed on a table.
I have been using react-bootstrap's components so decided to use the Modal component provided. (https://react-bootstrap.netlify.com/components/modal/#modals-live)
It was successfully working without any errors when I just called and used the component within App.tsx as follows:
const App: React.FC = () => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div className="App">
<NavBar/>
<Jumbotron fluid className="userJumbotron">
<Container>
<h1>Manage Users</h1>
<Button variant="outline-dark" onClick={handleShow}>Add new user</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Add User</Modal.Title>
</Modal.Header>
<Modal.Body><NewUserForm/></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
But I think realized that I'll need more than 1 modal component for my program and decided to make the modal component section into my own component that I can reuse as many times as I want and customize as I want within the App.tsx
So I decided to make a NewModal.tsx component that has the bootstrap modal component and button pre-made meaning I'd only have to call one line () rather than a whole chunk. the NewModal.tsx code is as follows:
export default class NewModal extends Component<any> {
constructor (props: any){
super(props)
this.state={
show:false
}
}
render() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div>
<h1>Manage Users</h1>
<Button variant="outline-dark" onClick={handleShow}>Add new user</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Add User</Modal.Title>
</Modal.Header>
<Modal.Body><NewUserForm/></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}
I am getting the following error from this code.
What is the cause for this error?
You can't use hooks inside class components, you need to change it to be a function based component, which can look something like this:
const NewModal = () => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div>
<h1>Manage Users</h1>
<Button variant="outline-dark" onClick={handleShow}>
Add new user
</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Add User</Modal.Title>
</Modal.Header>
<Modal.Body>
<NewUserForm />
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</div>
);
}
export default NewModal;