React router does not rendering anything - react-router

this is the signin code
import * as React from 'react';
import Avatar from '#mui/material/Avatar';
import Button from '#mui/material/Button';
import CssBaseline from '#mui/material/CssBaseline';
import TextField from '#mui/material/TextField';
import FormControlLabel from '#mui/material/FormControlLabel';
import Checkbox from '#mui/material/Checkbox';
import Link from '#mui/material/Link';
import Grid from '#mui/material/Grid';
import Box from '#mui/material/Box';
import LockOutlinedIcon from '#mui/icons-material/LockOutlined';
import Typography from '#mui/material/Typography';
import Container from '#mui/material/Container';
import { createTheme, ThemeProvider } from '#mui/material/styles';
const theme = createTheme();
export default function SignIn() {
const handleSubmit = (event) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
// eslint-disable-next-line no-console
console.log({
email: data.get('email'),
password: data.get('password'),
});
};
return (
<ThemeProvider theme={theme}>
<Container component="main" maxWidth="xs">
<CssBaseline />
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<Box component="form" onSubmit={handleSubmit} noValidate sx={{ mt: 1 }}>
<TextField
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
Sign In
</Button>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="#" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
</ThemeProvider>
);
}
this the signup code
import * as React from 'react';
import Avatar from '#mui/material/Avatar';
import Button from '#mui/material/Button';
import CssBaseline from '#mui/material/CssBaseline';
import TextField from '#mui/material/TextField';
import Link from '#mui/material/Link';
import Grid from '#mui/material/Grid';
import Box from '#mui/material/Box';
import LockOutlinedIcon from '#mui/icons-material/LockOutlined';
import Typography from '#mui/material/Typography';
import Container from '#mui/material/Container';
import { createTheme, ThemeProvider } from '#mui/material/styles';
const theme = createTheme();
export default function SignUp() {
const handleSubmit = (event) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
// eslint-disable-next-line no-console
console.log({
email: data.get('email'),
password: data.get('password'),
});
};
return (
<ThemeProvider theme={theme}>
<Container component="main" maxWidth="xs">
<CssBaseline />
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign up
</Typography>
<Box component="form" noValidate onSubmit={handleSubmit} sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<TextField
autoComplete="given-name"
name="firstName"
required
fullWidth
id="firstName"
label="First Name"
autoFocus
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
required
fullWidth
id="lastName"
label="Last Name"
name="lastName"
autoComplete="family-name"
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="new-password"
/>
</Grid>
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
Sign Up
</Button>
<Grid container justifyContent="flex-end">
<Grid item>
<Link href="#" variant="body2">
Already have an account? Sign in
</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
</ThemeProvider>
);
}
this the app.js
import React from 'react';
import ReactDOM from 'react-dom';
import SignUp from './containers/SignUp'
import {BrowserRouter as Router,Route} from 'react-router-dom'
import SignIn from './containers/SignIn';
import Home from "./containers/Home"
export default function App(){
return(
<Router>
<div>
<Route path="/"> <Home/> </Route>
<Route path="/signin"> <SignIn/> </Route>
<Route path="/signup"> <SignUp/> </Route>
</div>
</Router>
)
}
there is also a home.js i am sure it doesn't have any errors.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import SignUp from './containers/SignUp'
import SignIn from './containers/SignIn'
ReactDOM.render(
<React.StrictMode>
<App/>
</React.StrictMode>,
document.getElementById('root')
);
when I run this code it renders nothing . and also doesnt show any errors. please help me.
I have tried the above code . It shows no error. when I try to render a component without using routes it works perfectly fine.

The Route component API changed significantly in react-router-dom#6. The Route components are necessarily rendered directly by the Routes component and the routed components are rendered exclusively in the element prop.
Example:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import SignUp from './containers/SignUp';
import SignIn from './containers/SignIn';
import Home from './containers/Home';
export default function App() {
return(
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/signin" element={<SignIn />} />
<Route path="/signup" element={<SignUp />} />
</Routes>
</Router>
);
}

Related

How to have three elements in a row in React

I use React and Typescript.
I want to display these three elements next to each other in a row.
With the current code, the first button is on the left, but the input form and upload button are stacked on top of each other on the right. How can I make the three elements display in a row all next to each other?
return (
<Box padding={2}>
<Typography variant="h4">
<FormattedMessage defaultMessage="Add file" />
</Typography>
<Grid container alignItems="center" spacing={2} direction="row">
<Grid item>
<Button
startIcon={<Search />}
variant="contained"
component="label"
disabled={rulesFromFile.isLoading}
onClick={() => setUploadedFile(undefined)}
>
<FormattedMessage defaultMessage="Choose file" />
<input
type="file"
hidden
onChange={(event: ChangeEvent<HTMLInputElement>) =>
event.target.files && setSelectedFile(event.target.files[0])
}
/>
</Button>
</Grid>
{selectedFile && (!uploadedFile || rulesFromFile.isLoading) && (
<div>
<Grid item>
<form>
<TextField
type="text"
size="small"
style={{marginLeft: 4}}
label="someNumber"
variant="outlined"
value={someNumber}
onChange={e => setNumber(e.target.value)}
/>
</form>
</Grid>
<Grid item>
<LoadingButton
startIcon={<Upload />}
loadingPosition="start"
variant="contained"
color="secondary"
style={{marginLeft: 4}}
onClick={() => {
selectedFile &&
rulesFromFile.mutateAsync({
file: selectedFile,
someNumber: someNumber,
});
setUploadedFile(selectedFile);
}}
loading={rulesFromFile.isLoading}
>
<FormattedMessage defaultMessage="{fileName} upload" values={{fileName: selectedFile.name}} />
</LoadingButton>
</Grid>
</div>
)}
</Grid>
</Box>
);
Instead of a div tag, you need to use react fragment to keep items in a row
sth like this :
{selectedFile && (!uploadedFile || rulesFromFile.isLoading) && (
<>
<Grid item>...</Grid>
<Grid item>...</Grid>
</>
)}

When I click the submit button, it doesn't store to the database, but it keeps redirecting back to the form page

I'm using Reactjs and Material UI and then Formik for the form validation. Whenever I finish completing the form and then hit the submit button, it looks as if it's making the request to post the data to the back-end, but then it reload back to the same form page.
const initialValues = {
from: "",
to: "",
purpose: "",
date: "",
kilometer: "",
amount: "",
claimType: "",
fullname:"",
vehicleNo: "",
bank: "",
email: "",
department: "",
status:"",
};
useEffect(() => {
if(!localStorage.getItem("accessToken")){
history.push("/");
}
}, [])
const validationSchema = Yup.object().shape({
from: Yup.string().required(),
to: Yup.string().required() ,
purpose:Yup.string().required(),
date:Yup.date().required(),
kilometer:Yup.number().required(),
amount: Yup.number().required(),
claimType: Yup.string().required(),
fullname: Yup.string().required(),
vehicleNo: Yup.string().required(),
department: Yup.string().required(),
bank: Yup.string().required(),
email: Yup.string().email(),
status: Yup.string(),
});
const onSubmit = (data)=> {
axios
.post("http://localhost:5001/dutyMileage", data, {
headers:
{ accessToken: localStorage.getItem("accessToken")},
})
.then((response) => {
console.log("it worked");
history.push('/Home');
})
}
return (
<div>
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
validationSchema={validationSchema} >
<form className={classes.root} onSubmit={() => { alert("Claim Submitted"); }}>
<div className="formstep1">
<div>
<TextField
label="Full Name"
required
autoComplete="off"
variant="outlined"
name="fullname"
placeholder="Enter your Full name"
/>
<TextField
label="Department"
required
autoComplete="off"
variant="outlined"
name="department"
placeholder="Enter your department"
/>
</div>
<div>
<TextField
label="Bank"
required
autoComplete="off"
variant="outlined"
name="bank"
placeholder="Enter your bank name"
/>
<TextField
label="Date"
name="date"
variant="outlined"
/>
</div>
<div>
<TextField
disabled
variant="outlined"
label="status"
name="status"
value="PENDING"
/>
<TextField
label="Email"
required
autoComplete="off"
variant="outlined"
name="email"
placeholder="Enter your Email "
/>
</div>
<div className="select">
<InputLabel id="demo-simple-select-outlined-label">Claim Type</InputLabel>
<Select
required
name="claimType"
variant="outlined"
label="Claim Type"
value={claimType}
onChange={handleChange}
>
<MenuItem value="Duty Mileage">Duty Mileage</MenuItem>
<MenuItem value="Travelling Allowances">Travelling Allowances</MenuItem>
<MenuItem value="Approved Purchases">Approved Purchases</MenuItem>
<MenuItem value="Guest Of University">Guest Of University </MenuItem>
<MenuItem value="Other Claims">Other Claims</MenuItem>
</Select>
</div>
<div>
<TextField
label="Kilometer"
name="kilometer"
className={classes.root, classes.textField}
InputProps={{
endAdornment: <InputAdornment position="end">Km</InputAdornment>,
}}
variant="outlined"
onChange={ (event) => {
setKilometer(event.target.value);
}}
placeholder="Number of Kilometers"
/>
<TextField
label="Amount"
onChange={handleChangee}
name="amount"
InputProps={{
inputComponent: NumberFormatCustom,
}}
variant="outlined"
placeholder="Enter Amount In Naira"
/>
</div>
<div>
<TextField
label="From"
required
autoComplete="off"
variant="outlined"
placeholder="Journey From"
name="from" />
<TextField
label="To"
required
autoComplete="off"
variant="outlined"
name="to"
placeholder="journey To"
/>
</div>
<div>
<TextField
label="Vehicle Number"
required
autoComplete="off"
variant="outlined"
name="vehicleNo"
placeholder="Enter your Vehicle Number"
/>
<TextField
label="Purpose"
required
autoComplete="off"
variant="outlined"
name="purpose"
placeholder="purpose"
/>
</div>
</div>
<button type="submit"> Submit Claim</button>
</form>
</Formik>
</Paper>
</div>
);
}
And the back end goes like this
The router request:
const express = require("express");
const router = express.Router();
const { DutyMileage } = require("../models");
const { validateToken } = require("../middlewares/AuthMiddleware");
router.post("/", validateToken, async(req, res) => {
const post = req.body;
post.userId = req.username.userId;
post.StaffId = req.username.id;
await DutyMileage.create(post);
res.json(post);
});
Anytime I make request to submit the data to the database, it keeps reloading and it's stuck on the form page.
First, you must have errors in console, check inspection in browser and your node(npm console) errors
Second, here is code from formik official lib, try to remake you template for this to test:
<Formik
initialValues={{yourInitialValues}}
validationSchema={yourYupValidation}
onSubmit={(values, {setSubmitting, resetForm}) => {
// When button submits form and form is in the process of submitting, submit button is disabled
setSubmitting(true);
// Simulate submitting to database, shows us values submitted, resets form
setTimeout(() => {
//your code to send to API
//you can debug and test values here
alert(JSON.stringify(values, null, 2))
setSubmitting(false);
}, 1);
}}
>
{( {values,
errors,
touched,
handleChange,
handleBlur,
handleReset,
setFieldValue,
handleSubmit,
setFieldTouched,
isSubmitting }) => (
//use only formik functions to test
<form onSubmit={handleSubmit}>
</form>
)}
</Formik>
And last one: you have onSubmit={() => { alert("Claim Submitted"); }}, just check this line, you just console log onSubmit. Also your onSubmit const is outside Formik component, it may affect formik behaviour.

Clearing fields at the touch of a button

I have fields of auto-completion. When I press a button I want to clear the existing data and get clean fields.
I did this and it does not work:
<Autocomplete
id="combo-box-demo"
value={searchCases.NAME}
options={Cases}
getOptionLabel={(option) => option.NAME.toString()}
style={{ width: 200 }}
renderInput={(params) => (
<TextField {...params} label="name" variant="outlined" />
)}
onChange={(e) => onChange(e.target.innerText, "L_C_NUM")}
/>
<Autocomplete
id="combo-box-demo"
value={searchCases.AGE}
options={Cases}
getOptionLabel={(option) => option.AGE.toString()}
style={{ width: 200 }}
renderInput={(params) => (
<TextField {...params} label="age" variant="outlined" />
)}
onChange={(e) => onChange(e.target.innerText, "AGE")}
/>
That's the clean button
<Button onClick={() => handleReset()}>נקה נתונים</Button>
And that's the function:
const handleReset = () => {
setSearchCases({});
};
useEffect(()=>{
console.log(searchCases);
},[searchCases])

input fields overlapping in layout

I wanted to create a form with text field, age, country and gender. however there seems to be a problem. The age and gender field seems to be overlapping on each other. How do I make every input field be in it's own row instead of overlapping
codesandbox, the problem seems to be there only when you open the website in full
import React, { Fragment, useState } from "react";
import { Container, Row, Col, Form } from "react-bootstrap";
import {
CountryDropdown,
RegionDropdown,
CountryRegionData
} from "react-country-region-selector";
const App = () => {
const [age, setAge] = useState("");
const [gender, setGender] = useState("");
const [country, setCountry] = useState("");
const [text, setText] = useState("");
const handleSubmit = async () => {
console.log(age, gender, country, text);
};
return (
<Fragment>
<Container>
<Row md={4}>
<Col xs={12} md={7}>
<Form.Group controlId="textarea">
<Form.Label />
<Form.Control
as="textarea"
rows="20"
onChange={e => setText(e.target.value)}
placeholder="Enter you text"
/>
</Form.Group>
</Col>
<Col xs={12} md={5}>
<Form className="mb-3">
<Form.Row>
<Form.Group as={Row}>
<Form.Label>
Age
<Form.Control
type="text"
name="age"
value={age}
onChange={e => setAge(e.target.value)}
required
/>
</Form.Label>
</Form.Group>
<br />
<Form.Group controlId="exampleForm.SelectCustomSizeSm" as={Row}>
<Form.Label>Gender</Form.Label>
<Form.Control
as="select"
size="sm"
custom
value={gender}
onChange={e => setGender(e.target.value)}
>
<option>Male</option>
<option>Female</option>
<option>Prefer Not To Say</option>
</Form.Control>
</Form.Group>
<Form.Group>
<Form.Label>
Country
<CountryDropdown
value={country}
onChange={e => setCountry(e)}
/>
</Form.Label>
</Form.Group>
</Form.Row>
</Form>
<Form.Group as={Col}>
<input
type="submit"
className="btn btn-dark my-1"
value="Submit"
onClick={handleSubmit}
/>
</Form.Group>
</Col>
</Row>
</Container>
</Fragment>
);
};
export default App;
You need to first remove the as={Row} attributes from both the Age and Gender form group as its not the use case for what you are trying to achieve. The <Form.Label> of the age form group component is not used properly.
After making those changes it worked fine. Here is a snippet
import React, { Fragment, useState } from "react";
import { Container, Row, Col, Form } from "react-bootstrap";
import {
CountryDropdown,
RegionDropdown,
CountryRegionData
} from "react-country-region-selector";
const App = () => {
const [age, setAge] = useState("");
const [gender, setGender] = useState("");
const [country, setCountry] = useState("");
const [text, setText] = useState("");
const handleSubmit = async () => {
console.log(age, gender, country, text);
};
return (
<Fragment>
<Container>
<Row md={4}>
<Col xs={12} md={7}>
<Form.Group controlId="textarea">
<Form.Label />
<Form.Control
as="textarea"
rows="20"
onChange={e => setText(e.target.value)}
placeholder="Enter you text"
/>
</Form.Group>
</Col>
<Col xs={12} md={5}>
<Form className="mb-3">
<Form.Row>
<Form.Group>
<Form.Label>
Age
</Form.Label>
<Form.Control
type="text"
name="age"
value={age}
onChange={e => setAge(e.target.value)}
required
/>
</Form.Group>
<br />
<Form.Group controlId="exampleForm.SelectCustomSizeSm">
<Form.Label>Gender</Form.Label>
<Form.Control
as="select"
size="sm"
custom
value={gender}
onChange={e => setGender(e.target.value)}
>
<option>Male</option>
<option>Female</option>
<option>Prefer Not To Say</option>
</Form.Control>
</Form.Group>
<Form.Group>
<Form.Label>
Country
<CountryDropdown
value={country}
onChange={e => setCountry(e)}
/>
</Form.Label>
</Form.Group>
</Form.Row>
</Form>
<Form.Group as={Col}>
<input
type="submit"
className="btn btn-dark my-1"
value="Submit"
onClick={handleSubmit}
/>
</Form.Group>
</Col>
</Row>
</Container>
</Fragment>
);
};
export default App;
The easiest solution is to remove as={Row} from <Form.Group as={Row}>.
<Container>
<Row md={4}>
<Col xs={12} md={7}>
{/* ... */}
</Col>
<Col xs={12} md={5}>
<Form className="mb-3">
<Form.Row>
{/* <Form.Group as={Row}> */}
<Form.Group>
<Form.Label>
Age
<Form.Control type="text" name="age" required />
</Form.Label>
</Form.Group>
<br />
{/* <Form.Group controlId="exampleForm.SelectCustomSizeSm" as={Row}> */}
<Form.Group controlId="exampleForm.SelectCustomSizeSm">
<Form.Label>Gender</Form.Label>
<Form.Control as="select" size="sm" custom>
<option>Male</option>
<option>Female</option>
<option>Prefer Not To Say</option>
</Form.Control>
</Form.Group>
<Form.Group>{/* ... */}</Form.Group>
</Form.Row>
</Form>
<Form.Group as={Col}>{/* ... */}</Form.Group>
</Col>
</Row>
</Container>
Alternatively, you can remove <Form.Row /> entirely. The solution you choose depends on the layout you expect.

React Router v4 Component not loaded on button submit

I have a login form and when I click login, the URL is updated but the component is not. (e.g. localhost:8080/somewhere but still on login page)
The versions of my packages are as follows:
react - 15.4.2
react-router & react-router-dom - 4.1.1
redux-form - 6.6.1
This is the Login component
class Login extends React.Component {
handleFormSubmit = ( values ) => {
this.props.signInUser(values);
history.push('/somewhere');
};
<div>
<div>
<h2>Log In</h2>
<form onSubmit={ this.props.handleSubmit( this.handleFormSubmit ) }>
<Field name="email" type="text" label="Email"/>
<Field name="password" type="password" label="Password"/>
<button action="submit">Sign In</button>
</form>
</div>
</div>
...
}
export default connect( mapStateToProps, Actions, )( reduxForm({
form: 'login',
validate,})( Login ));
I am using history.push because I have a shared history object.
My routes are as follows:
<Provider store={ store }>
<Router history={history}>
< App >
<Switch>
<Route exact path="/" component={ Home }/>
<Route path="/login" component={ Login } />
<Route path="/somewhere" component={ Somewhere } />
</Switch>
</ App >
</Router>
</Provider>
I tried using <Redirect> but can't get it to work. Also tried using withRouter but discovered this is only applicable for components not declared in the routes.
How do I redirect to the Somewhere component when submitting the form?
I'm not sure that this is the best way to do this, but it works for me :
<form onSubmit={ this.props.handleSubmit( this.handleFormSubmit ) }>
<Field name="email" type="text" label="Email"/>
<Field name="password" type="password" label="Password"/>
<button action="submit">Sign In</button>
{this.props.user.loggedIn && <Redirect to={'/Somewhere'} />}
</form>
Given the fact that this.props.handleSubmit( this.handleFormSubmit ) dispatches an action who toggles to true the loggedIn prop of user.
You have to map user to props, for your component to re-render when user.loggedIn is changed. The <Redirect> will then be activated.