Why is submitting a form resetting my state? - javascript

I am making a Kanban board project. It comes with a log in screen. I've added a button that I want to use to add new tasks to the board. However, when I submit to that button, it resets my email state to blank, which is my condition to returning to the log-in screen. Why? How can I prevent this? Any advice would be appreciated.
App.js
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
initialData,
email: this.props.email,
password: this.props.password,
showForm: false,
};
this.logOut = this.logOut.bind(this);
}
logOut() {
console.log("Logged out");
this.setState({ email: "", password: "" });
}
render() {
const { showForm } = this.state;
if (this.state.email == "") {
return <LogIn />;
} else {
{
//console.log(this.state);
}
return (
<DragDropContext onDragEnd={this.onDragEnd}>
<Container>
{this.state.initialData.columnOrder.map((columnId) => {
const column = this.state.initialData.columns[columnId];
const tasks = column.taskIds.map(
(taskId) => this.state.initialData.tasks[taskId]
);
return <Column key={column.id} column={column} tasks={tasks} />;
})}
</Container>
<button onClick={this.logOut}>Log Out</button>
<button onClick={() => this.hideComponent("showForm")}>
Create Task
</button>
<Container>
<div>
{showForm && <CreateForm onSubmit={(value) => alert(value)} />}
</div>
</Container>
</DragDropContext>
);
}
}
}
CreateForm.js
class CreateForm extends React.Component {
render() {
console.log("form");
return (
<form onSubmit={this.handleSubmit}>
<label>
Content:
<input type="text" />
</label>
<input type="submit" value="Submit" onSubmit={event => props.onSubmit(event.target.value)}/>
</form>
);
}
}
export default CreateForm;

handleSubmit(event) {
event.preventDefault(); // we need this for avoid your behavior
// your code
}

Related

Component is not defined in react?

using login function as component throws an error like this:
'LoginModal' is not defined react/jsx-no-undef
I dont know why this happening.
Thanks in advance.
export default class Login extends Component {
state={
loading: false,
modalShow: false,
clicked: false,
password:''
}
LoginModal = () => {
return <Modal {...this.props} size="lg" aria-labelledby="contained-modal-title-vcenter">
<Modal.Header closeButton>An otp has been sent to your Email!</Modal.Header>
<p>something...</p>
<Button variant="outline-primary" onClick={this.setState({modalShow:false})} >Change Password</Button>
</Modal>
}
handleForgetPassword = () => {
this.setState({modalShow: true})
}
handleSubmit = (event) => {
.....
}
render() {
return (
<div>
<div id="login-wrapper">
<p onClick={this.handleForgetPassword} className="forgot-password">forgot password?</p>
</div>
</div>
<LoginModal
show={this.state.modalShow}
onHide={() => this.setState({modalShow:false})}/>
</div>
)
}
}
You should initialize the state in the constructor
https://reactjs.org/docs/react-component.html#constructor
constructor(props) {
super(props);
this.state={
loading: false,
modalShow: false,
clicked: false,
password:''
}
Also, fix the render method as it's having a missing , or an extra closing tag
render() {
return (
<div>
<div id="login-wrapper">
<p onClick={this.handleForgetPassword} className="forgot-password">forgot password?</p>
</div>
<LoginModal
show={this.state.modalShow}
onHide={() => this.setState({modalShow:false})}/>
</div>
)
}
You're not referencing LoginModal correctly. You should do something like this instead:
Create a standalone component and then pass props to it
const LoginModal = ({onClick, ...props}) => {
return <Modal {...props} size="lg" aria-labelledby="contained-modal-title-vcenter">
<Modal.Header closeButton>An otp has been sent to your Email!</Modal.Header>
<p>something...</p>
<Button variant="outline-primary" onClick={onClick} >Change Password</Button>
</Modal>
}
Try this way
return (
<div>
......
{this.LoginModal()}
</div>
)

How to pass props to one React Class to Another React Class?

I am trying to have a button enabled in a modal when text is entered in an input field. But my form is built in another class and is used in a parent class. How can I pass an onChange method my form component.
Here is my parent component:
import React from 'react';
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle
} from '#material-ui/core';
import CompanyFinancialModalForm from '../CompanyFinancialModalForm/CompanyFinancialModalForm';
interface CompanyFinancialModalState {
addEnabled: boolean;
}
interface CompanyFinancialModalProps {
open: boolean;
onClose: () => void;
}
export class CompanyFinancialModal extends React.Component<
CompanyFinancialModalProps,
CompanyFinancialModalState
> {
constructor(props: CompanyFinancialModalProps) {
super(props);
this.state = {
addEnabled: false
};
}
private enableButton = () => {
this.setState({ addEnabled: true});
}
public render() {
const { open, onClose } = this.props;
const { addEnabled } = this.state;
return (
<>
<Dialog
open={open}
onClose={onClose}
className="company-financial-modal"
>
<DialogTitle id="company-financial-modal-title">
{'Company and Financial Data'}
</DialogTitle>
<DialogContent>
<CompanyFinancialModalForm onChange={this.enableButton}/>
</DialogContent>
<DialogActions>
<Button
id="company-financial-modal-add"
disabled={!addEnabled}
onClick={onClose}
color="primary"
>
Add
</Button>
<Button
id="company-financial-modal-cancel"
onClick={onClose}
color="secondary"
autoFocus={true}
>
Cancel
</Button>
</DialogActions>
</Dialog>
</>
);
}
}
export default CompanyFinancialModal;
Here is my class that my form is in:
import React from 'react';
import axios from 'axios';
import { Form, Field } from 'react-final-form';
import { TextField, Select } from 'final-form-material-ui';
import {
Paper,
Grid,
MenuItem,
} from '#material-ui/core';
export interface IValues {
company_name: string;
critical_technology: [];
}
export interface IFormState {
[key: string]: any;
values: IValues[];
submitSuccess: boolean;
}
export default class CompanyFinancialModalForm extends React.Component<{}, IFormState> {
constructor(props: {}) {
super(props);
this.state = {
company_name: '',
critical_technology: [],
values: [],
submitSuccess: false
};
}
private processFormSubmission = (e: React.FormEvent<HTMLFormElement>): void => {
e.preventDefault();
this.setState({ loading: true });
const formData = {
company_name: this.state.company_name,
critical_technology: this.state.critical_technology
};
this.setState({
submitSuccess: true,
values: [...this.state.values, formData],
loading: false
});
axios.post(`http://localhost:8081/companies`, formData);
}
private onChange = (e: React.FormEvent<HTMLInputElement>) => {
const { name, value } = e.target;
// other form-related logic
this.props.onChange({ name, value }, e);
}
public render() {
const { submitSuccess, loading } = this.state;
const { onChange } = this.props;
return (
<div>
<Form
onSubmit={this.processFormSubmission}
// validate={this.validateForm}
render={({ handleSubmit,/* reset, submitting, pristine, values*/ }) => (
<form onSubmit={handleSubmit} noValidate>
<Paper style={{ padding: 16 }}>
<Grid container alignItems="flex-start" spacing={2}>
<Grid item xs={6}>
<Field
fullWidth
required
name="companyName"
component={TextField}
type="text"
label="Company Name"
onChange={onChange}
/>
</Grid>
<Grid item xs={12}>
<Field
name="critical_technology"
label="Critical Technology"
component={Select as any}
>
<MenuItem value="hypersonics">Hypersonics</MenuItem>
<MenuItem value="directed_energy">Directed Energy</MenuItem>
<MenuItem value="command_control_and_communications">Command, Control and Communications </MenuItem>
<MenuItem value="space_offense_and_defense">Space Offense and Defense</MenuItem>
<MenuItem value="cybersecurity">Cybersecurity</MenuItem>
<MenuItem value="artificial_intelligence_machine_learning">Artificial Intelligence/Machine Learning</MenuItem>
<MenuItem value="missile_defense">Missile Defense</MenuItem>
<MenuItem value="quantum_science_and_computing">Quantum Science and Computing </MenuItem>
<MenuItem value="microelectronics">Microelectronics</MenuItem>
<MenuItem value="autonomy">Autonomy</MenuItem>
</Field>
</Grid>
</Grid>
</Paper>
</form>
)}
/>
</div>
);
}
}
I want to pass a prop to <CompanyFinancialModalForm /> that enables the add button when the Textfield has text typed into it.
For future reference, it will be more beneficial if you only include the relevant code, because it takes more time to find when scrolling through irrelevant code, anyways:
I'm not 100% clear on what you're looking for, but I'll try to answer what I think I understand. You can add an onChange method on your parent component, and pass that as a prop to the form, and the form can call that function every time it runs it's own onChange method. Below is a simplified version:
class Parent extends Component {
state = {
buttonEnabled: false,
// formInputValue: '', <-- if you need this
};
// - omitting constructor/bind for simplicity for now
onChange({ name, value }, e) {
// your logic to determine whether button is enabled or not
// this is just me guessing what you want to implement
if (value) this.setState({ buttonEnabled: true });
else this.setState({ buttonEnabled: false });
}
render() {
return (
<Fragment>
<YourForm onChange={this.onChange} />
<Button enabled={this.state.buttonEnabled} />
</Fragment>
);
}
}
class YourForm extends Component {
onChange(e) {
const { name, value } = e.target;
// other form-related logic
this.props.onChange({ name, value }, e);
}
}
is this what you're looking for?
You can simply pass a child a reference to a function that exists in the parent and then use the parent's function to validate and enable the button.
Codesandbox Demo
Simplified Code:
function Child (props) {
return (
<input type="text" onChange={props.doIt}/>
)
}
function App() {
const [disabled, setDisabled] = useState(true);
function doIt(e) {
setDisabled(e.currentTarget.value.length === 0);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Child doIt={doIt} />
<button disabled={disabled}>Add</button>
</div>
);
}

React - render CSS animation onClick

I'm new to React, sorry if this is too basic.
I am trying to render a simple animation when <Link> is clicked in React.
I have Coffees.jsx:
import Brewing from './Brewing.jsx';
handleClick() {
return (<Brewing/>)
}
render(){
return (
<div>
<div>
<Link onClick={this.handleClick} to="/brewing">Coffee</Link>
</div>
</div>
);
}
}
export default Menus;
and Brewing.jsx:
import './css/mug.css'
class Brewing extends Component {
constructor (props) {
super(props);
};
render() {
return (
<div>
<div className="cup">
<div className="coffee"></div>
</div>
<div className="smoke"></div>
</div>
);
}
}
export default Brewing;
The above is not working. It only works if I inject the animation:
<div className="cup">
<div className="coffee"></div>
</div>
<div className="smoke"></div>
directly into Coffees.jxs, like so:
render(){
return (
<div>
<div>
<div className="cup">
<div className="coffee"></div>
</div>
<div className="smoke"></div>
<Link to="/brewing"></Link>
</div>
</div>
);
}
But this is not desired...How do I render this animation at onClick?
EDIT:
App.jsx
class App extends Component {
constructor() {
super();
this.state = {
users: [],
isAuthenticated: false,
messageName: null,
messageType: null,
select:'',
email: '',
id: '',
username: '',
active: '',
admin: '',
//task:''
};
this.logoutUser = this.logoutUser.bind(this);
this.loginUser = this.loginUser.bind(this);
this.createMessage = this.createMessage.bind(this);
this.removeMessage = this.removeMessage.bind(this);
this.userId = this.userId.bind(this);
};
componentWillMount() {
if (window.localStorage.getItem('authToken')) {
this.setState({ isAuthenticated: true });
};
};
componentDidMount() {
this.getUsers();
this.userId();
};
getUsers() {
axios.get(`${process.env.REACT_APP_WEB_SERVICE_URL}/users`)
.then((res) => { this.setState({ users: res.data.data.users }); })
.catch((err) => { });
};
logoutUser() {
window.localStorage.clear();
this.setState({ isAuthenticated: false });
};
loginUser(token) {
window.localStorage.setItem('authToken', token);
this.setState({ isAuthenticated: true });
this.getUsers();
this.createMessage('Welcome', 'success');
};
userId(event) {
const options = {
url: `${process.env.REACT_APP_WEB_SERVICE_URL}/auth/status`,
method: 'get',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${window.localStorage.authToken}`
}
};
return axios(options)
.then((res) => {
console.log(res.data.data)
this.setState({
select: res.data.data.select,
email: res.data.data.email,
id: res.data.data.id,
username: res.data.data.username,
active: String(res.data.data.active),
admin: String(res.data.data.admin),
})
})
.catch((error) => { console.log(error); });
};
createMessage(name='Sanity Check', type='success') {
this.setState({
messageName: name,
messageType: type
});
setTimeout(() => {
this.removeMessage();
}, 3000);
};
removeMessage() {
this.setState({
messageName: null,
messageType: null
});
};
render() {
return (
<div>
<NavBar
title={this.state.title}
isAuthenticated={this.state.isAuthenticated}
/>
<section className="section">
<div className="container">
{this.state.messageName && this.state.messageType &&
<Message
messageName={this.state.messageName}
messageType={this.state.messageType}
removeMessage={this.removeMessage}
/>
}
<div className="columns">
<div className="column is-half">
<br/>
<Switch>
<Route exact path='/about' component={About}/>
<Route exact path='/register' render={() => (
<Form
formType={'Register'}
isAuthenticated={this.state.isAuthenticated}
loginUser={this.loginUser}
createMessage={this.createMessage}
userId={this.state.id}
/>
)} />
<Route exact path='/login' render={() => (
<Form
formType={'Login'}
isAuthenticated={this.state.isAuthenticated}
loginUser={this.loginUser}
createMessage={this.createMessage}
userId={this.state.id}
/>
)} />
<Route exact path='/logout' render={() => (
<Logout
logoutUser={this.logoutUser}
isAuthenticated={this.state.isAuthenticated}
/>
)} />
<Route exact path='/status' render={() => (
<UserStatus
isAuthenticated={this.state.isAuthenticated}
/>
)} />
<Route exact path='/seeds' render={() => (
<Seeds
isAuthenticated={this.state.isAuthenticated}
userId={this.state.id}
/>
)} />
<Route exact path='/menus' render={() => (
<Menus
isAuthenticated={this.state.isAuthenticated}
userId={this.state.id}
/>
)} />
<Route exact path='/coffee' render={() => (
<Coffees
isAuthenticated={this.state.isAuthenticated}
userId={this.state.select}
/>
)} />
</Switch>
</div>
</div>
</div>
</section>
</div>
)
}
};
export default App;
When you click any Link it will not wait on that component to execute any event, it will simply redirect to given path (to="/coffees"), so you need Route to handle this path.
Instead of Link we can use a button or simply a div (you can style it so that it look like link) and write onClick handler on that. In that handler we need to add a setTimeout with the timeout of actual animation.
Now when setTimeout executes, we can set a variable in state which will help us to redirect to desired component.
Your menu component should be,
class Menu extends React.Component{
constructor(props){
super(props);
this.state = {
isLoading: false,
redirect: false
}
}
gotoCoffee = () => {
this.setState({isLoading:true})
setTimeout(()=>{
this.setState({isLoading:false,redirect:true})
},5000) //Replace this time with your animation time
}
renderCoffee = () => {
if (this.state.redirect) {
return <Redirect to='/coffees' />
}
}
render(){
return(
<div>
{this.state.isLoading && <Brewing />}
{this.renderCoffee()}
<div onClick={this.gotoCoffee} style={{textDecoration:'underline',color:'blue',cursor:'pointer'}}>Go to Coffee</div>
</div>
)
}
}
I have used Redirect from react-router-dom package for navigation.
Demo
There are a few things to consider with your Menus component;
returning the <Brewing> JSX from handleClick() won't affect the rendering result of the Menus component, meaning that the animation in <Brewing> won't show as required
you'll need to track some state to determine if the <Link> has been clicked by the user at which point, your Menus component can render the <Brewing> component (ie that contains the animation)
One way to approach that in code would be to make the following changes in Coffee.jsx:
import Brewing from './Brewing.jsx';
class Menus extends React.Component {
constructor(props) {
super(props);
/*
Set inital state to false, which means Brewing wont initially show
*/
this.state = { hasBeenClicked : false };
}
}
handleClick() {
/*
Set hasBeenClicked state of Menus to true after click which will
cause Brewing to be rendered
*/
this.setState({ hasBeenClicked : true });
}
render(){
return (
<div>
<div>
{ /*
This is short hand for "if hasBeenClicked = true, then
render Brewing here
*/ }
{ (this.state.hasBeenClicked === true) && <Brewing/> }
<Link onClick={this.handleClick} to="/brewing">Coffee</Link>
</div>
</div>
);
}
}
export default Menus;

how when the login is successful the token already exists, it will move to the home page?

If you successfully log in and have got the token, then the page will redirect to home and after I have successfully logged in and got the token, see the picture taken .
.
the code is in the login folder, thank you for helping .
const FormItem = Form.Item;
class Login extends Component {
constructor(props) {
super(props);
this.state = {
isAuthenticated: this.props.isAuthenticated,
errorMessage: null,
isErorloaded: false
};
}
handleRegisterGoogle = request => {
this.props.loginWithGoogle(this.props.history, request);
};
handleSubmit = e => {
try {
e.preventDefault();
this.props.form.validateFields(async (err, values) => {
if (!err) {
console.log("Received values of form: ", values);
await this.props.loginWithForm(values);
}
});
} catch (error) {
console.log(error);
}
};
render() {
console.log(this.props.token);
const { form } = this.props;
const { getFieldDecorator } = form;
const { errorMessage, isErorloaded,isAuthenticated } = this.state;
if (isAuthenticated === true) {
return <Redirect to="/" />;
}
console.log(errorMessage);
return (
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem className="login-form__input-text">
{getFieldDecorator("email", {
rules: [
{
type: "email",
required: true,
message: "Please input your email!"
}
]
})(
<Input
size={"large"}
prefix={
<Icon type={"user"} style={{ color: "rgba(0,0,0,.25)" }} />
}
placeholder={"Email"}
/>
)}
</FormItem>
<FormItem className="login-form__input-text">
{getFieldDecorator("password", {
rules: [
{
required: true,
message: "Please input your password!"
}
]
})(
<Input
size={"large"}
prefix={
<Icon type={"lock"} style={{ color: "rgba(0,0,0,.25)" }} />
}
placeholder={"Password"}
type="password"
/>
)}
</FormItem>
<FormItem className="login-form__checkBox">
{getFieldDecorator("remember", {
valuePropName: "checked",
initialValue: true
})(<Checkbox>{strings.login_remember_me}</Checkbox>)}
<a className="login-form__forgot" href="/">
{strings.login_forgot_password}
</a>
<div>
<Button
size={"large"}
htmlType="submit"
className="login-form__button__submit"
>
<h4>{strings.login_enter}</h4>
</Button>
<div className="login-form__error-box">
{isErorloaded ? (
<p className="login-form__error-notif"> {errorMessage}</p>
) : null}
</div>
</div>
<div className="login-form__separator">
<p className="login-form__separator__text">
{strings.login_option}
</p>
</div>
<div className="login-form__socmed-box">
<ButtonFacebook
className="login-form__socmed-button"
onSubmit={this.handleRegisterGoogle}
>
<p> {strings.facebook}</p>
</ButtonFacebook>
<ButtonGoogle
className="login-form__socmed-button"
onSubmit={this.handleRegisterGoogle}
>
<p> {strings.google}</p>
</ButtonGoogle>
</div>
<p style={{ marginTop: "70px" }}>
{strings.formatString(
strings.login_quote,
<a href="/register" className="login-form__register">
{strings.login_register}{" "}
</a>
)}
</p>
</FormItem>
</Form>
);
}
}
const mapStateToProps = state => ({
isAuthenticated: state.authentication.isAuthenticated,
token: state.authentication.token
});
const LoginForm = Form.create({})(Login);
export default connect(
mapStateToProps,
{ loginWithGoogle, loginWithForm }
)(LoginForm);

How to pass props from a reusable form in React

I'm building a reusable form in React to be used as login and signin forms in may app.
I'm using Axios to send the data to the database.
But I can't send the input values as props to my UserSignIn component to use them in a function with Axios. Here's the code :
How do I get these props ? Thanks
AccountForm component :
import React, { Component } from "react";
import {Grid,Input, InputLabel, FormControl, Typography, Button, Paper,
} from "#material-ui/core";
class AccountForm extends Component {
constructor(props) {
super(props);
this.state = {
userSignUpName: "",
userSignUpEmail: ""
}
handleChange(e) {
this.setState({
[e.target.id]: e.target.value
});
}
render() {
const {
classes,
formType,
onCreateAccount,
onSubmit,
onBlurCheck,
message,
title
} = this.props;
const {
userSignUpName,
userSignUpEmail,
} = this.state;
return (
<div>
<Grid container justify="center">
<Grid item xs={10}>
<Paper>
<form
onChange={e => this.handleChange(e)}
onSubmit={onSubmit}
>
<Typography variant="subheading" color="primary"
align="center">
{title}
</Typography>
{formType === "signin" && (
<FormControl>
<InputLabel htmlFor="name">Nom</InputLabel>
<Input id="userSignUpName" name="name" type="text" />
</FormControl>
)}
<FormControl>
<InputLabel htmlFor="email">Email</InputLabel>
<Input id="userSignUpEmail" type="email" name="email" />
</FormControl>
</form>
</Paper>
</Grid>
</Grid>
</div>
);
}
}
export default AccountForm;
UserSignIn component :
import React, { Component } from "react";
import axios from "axios";
import config from "../../assets/lib/axiosConfig";
import { AccountForm } from "./Index";
class UserSignIn extends Component {
constructor(props) {
super(props);
this.state = {
formType: "signin",
title: "Create account"
};
}
handleSubmit(e) {
e.preventDefault();
axios(
config(
{
name: this.props.userSignUpName,
email: this.props.userSignUpEmail,
},
"/createAccount",
"post"
)
).then(res => {
const { success, error, token } = res.data;
if (success) {
localStorage.setItem("AuthToken", token);
this.props.redirectTo();
}
if (error) {
this.setState({ message: error });
}
});
}
render() {
const { prevPath, history, userSignUpName } = this.props;
// I can't get userSignUpName props
const { formType, message, title } = this.state;
return (
<AccountForm
{...this.props}
title={title}
onSubmit={e => this.handleSubmit(e)}
formType={formType}
redirectTo={
prevPath !== null && prevPath === "/mycart"
? () => history.push("/payment")
: () => history.push("/")
}
/>
);
}
}
export default UserSignIn;
Thanks
You can pass form data as handleSubmit parameters
AccountForm component :
<form
onChange={e => this.handleChange(e)}
onSubmit={(e) => {
e.preventDefault()
onSubmit({
userSignUpName: this.state.userSignUpName,
userSignUpEmail: this.state.userSignUpEmail,
})
}}
>
UserSignIn component :
handleSubmit(params) {
axios(
config(
{
name: params.userSignUpName,
email: params.userSignUpEmail,
},
//....
}

Categories

Resources