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.
Related
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>
);
}
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.
I am trying to use Formik in React for a dummy app. I am not being able to type anything in either of the input boxes if I give value as a prop. On the other hand, if I skip the value props, then I can type in the boxes but the same is not reflected as the value while submitting.
Here's the code:
export default class DashboardPage extends React.Component {
render() {
return (
<Formik
initialValues={{ fname: "", lname: "" }}
onSubmit={(values) => {
alert(values.fname);
}}
render={({ values, handleChange, handleSubmit }) => (
<form onSubmit={handleSubmit}>
<input type="text" placeholder="First Name" name="fname" onChange={handleChange} value={values.fname} />
<input type="text" placeholder="Last Name" name="lname" onChange={handleChange} value={values.lname} />
<button type="submit>ADD<button/>
</form>
)}
/>
);
}
}
I may be very wrong here and might be over-looking a minor error, but any help/suggestion is appreciated!
export default class DashboardPage extends React.Component {
render() {
return (
<Formik
initialValues={{ fname: "", lname: "" }}
onSubmit={ (values) => alert(values.fname) }
>
{ props => (
<React.Fragment>
<form onSubmit={handleSubmit}>
<input type="text" placeholder="First Name" name="fname" onChangeText={props.handleChange('fname')} />
<input type="text" placeholder="Last Name" name="lname" onChangeText={props.handleChange('lname')} />
<button type="submit>ADD<button/>
</form>
</React.Fragment>
)}
</Formik>
)
}
}
Hi mate can you please try this?
Another possibility for this weird behavior is putting your component inside a function and sending the props as function parameters instead of using a functional component with props as parameters.
When a component is inside a function you lose react component lifecycle and the parameters will not refresh even when its values change.
Make sure your form elements are properly configured as react elements.
Mine was also not working, I gave id prop in my TextField and now it works
const formik = useFormik({
initialValues: {
username: "",
password: "",
},
onSubmit: (values) => {
console.log(values);
// onLogin(values.username, values.password);
},
});
<form onSubmit={formik.handleSubmit}>
<TextField
value={formik.values.username}
onChange={formik.handleChange}
id="username"
name="username"
variant="outlined"
style={TextField1style}
placeholder="Enter username"
fullWidth
required
//.
// .
// .
// other code
enter image description here
I have this simple piece of code in my ReactJs app:
import React from 'react'
import '../../../assets/styles/authentication/login.css'
import '../../../assets/bootstrap/css/bootstrap.min.css'
import { login } from './login_form_actions.js'
export default class LoginForm extends React.Component {
constructor(props) {
super(props)
this.state = {
email : { email: "" },
password : { password: "" }
}
this.handle_sign_in_click = this.handle_sign_in_click.bind(this)
}
handle_sign_in_click(e) {
console.log(e, this.state.email, this.state.password)
login(this.state.email, this.state.password)
}
render() {
return (
<div className="col-sm-6 col-sm-offset-3 form-box">
<div className="form-auth">
<form className="login-form">
<div className="form-group">
<label className="sr-only" htmlFor="form-username">Email</label>
<input type="text" name="form-username" placeholder="Email..."
className="form-username form-control" id="form-username"
onChange={(event) => this.setState({email:event.target.value})}/>
</div>
<div className="form-group">
<label className="sr-only" htmlFor="form-password">Password</label>
<input type="password" name="form-password" placeholder="Password..."
className="form-password form-control" id="form-password"
onChange={(event) => this.setState({password:event.target.value})}/>
</div>
<button className="btn" onClick={this.handle_sign_in_click}>Sign in!</button>
</form>
</div>
</div>
)
}
}
When I click the Sign In button, nothing happens for some reason.
I tried to bind the handle_sign_in_click as proposed in some other reactjs question (from StackOverflow) but still nothing.. What am I missing here? (next step is to use redux to store the result of the auth on success)
Thanks for any help
Edit1: Console and proposition
console:
react-dom.development.js:22287 Download the React DevTools for a better development experience: react-devtools
authentication:1 [DOM] Input elements should have autocomplete attributes (suggested: "current-password"):
However, when I use an <a/> instead of <button/>, it does work but my design is broken (it's the same at all as when it's a button)
Here is how to properly handle basic forms in React (without libs like Formik etc...):
import React from 'react';
export default class Form extends React.Component {
state = { email: '', password: '' };
handleChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
handleSubmit = event => {
event.preventDefault();
// login logic here ususally passed down as props from the parent (if not using redux...) so it will be something like this.props.login(...)
this.setState({ email: '', password: '' });
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
name="email"
type="text"
onChange={this.handleChange}
placeholder="email"
value={this.state.email}
/>
<input
name="password"
type="text"
onChange={this.handleChange}
placeholder="password"
value={this.state.password}
/>
<input type="submit" />
</form>
);
}
}
You are missing a e.preventDefault in your signin handler, check this working sample
I am new to react redux loading bar and redux forms
on submit of a button I am trying to load the loading bar.
but the problem is when I load the loading bar. I am getting below error
proxyConsole.js:72 TypeError: Cannot read property 'default' of undefined
I debugged and found the error comes from only in this file proxyConsole.js
but I didn't include this file.
all my loading bar code is in this file SyncValidationForm.js
can you tell me how to fix it.
so that in future I will it myself.
providing my code snippet and sandbox below.
not sure how to fix the package files error
https://codesandbox.io/s/zn812n05v4
const SyncValidationForm = props => {
const { handleSubmit, pristine, reset, submitting } = props;
return (
<div>
<LoadingBar />
<form onSubmit={handleSubmit}>
<Field
name="username"
type="text"
component={renderField}
label="Username"
/>
<Field
name="email"
type="email"
component={renderField}
label="Email"
/>
<Field name="age" type="number" component={renderField} label="Age" />
<div>
<button type="submit" disabled={submitting}>
Submit
</button>
<button
type="button"
disabled={pristine || submitting}
onClick={reset}
>
Clear Values
</button>
</div>
</form>
</div>
);
};
You have included the component LoadingBar but it is not connected to the store.
The correct usage for rendering the LoadingBar component can be found here
If you wish not to use the middleware, you can dispatch the action to show/hide the LoadingBar based on example in this link. You can dispatch the action in your handleSubmit method.
Hope this helps!