Property not found in props of React element `form` - reactjs

Hi i'm having problems with Flow and React.
I'm getting these errors and I want to get rid of them. What am I missing I have search everywhere. I understand that the props are missing but I can't seem to find where to define them.
Flow: property className. Property not found in props of React element form
Flow: property onSubmit. Property not found in props of React element form
export default class LoginForm extends React.Component {
_submitForm: Function;
constructor(props?: {}) {
super(props);
this.state = {
form: {
email: '',
password: '',
},
errors: {
_form: "",
email: "",
password: ""
}
};
this._submitForm = this._submitForm.bind(this);
}
_handleValues(param: string, value?: string) {
let obj = this.state;
obj['form'][param] = value;
this.setState(obj);
}
_submitForm(event: Event) {
this._clearErrors(event);
let form = this.state.form;
AxiosQueue
.post({
url: LINK.AUTHENTICATE,
data: form
})
.then(({data}) => {
if (!data.success) {
return;
}
})
.catch((response) => {
console.error(response);
});
}
render() {
const {errors, form} = this.state;
const user = UserStore.getUser();
const formText = FORM_TEXT[user.language || "en_AU"];
return (
<form className="form-inline" onSubmit={this._submitForm}>
{errors._form}
<InputEmail id="email" error={errors.email} value={form.email} callback={this._handleValues}/>
<InputPassword id="password" error={errors.password} value={form.password}
callback={this._handleValues}/>
<button type="submit" className="btn btn-default">{formText.LOGIN}</button>
</form>
);
}
}

There is conflict with your variable name form in Syntex const {errors, form} = this.state; and form component. Solution is to give some other name in this.state. Like
this.state = {
formValidation:{
//Validation properties
}
}
And consume so that will remove conflict
const {formValidation} = this.state

Related

How can I pass my state to this class component in ReactJs/.Net?

I followed a tutorial to make an Asp.Net Core MVC app with a ReactJs front end (https://reactjs.net/tutorials/aspnetcore.html). I've been adding additional functionality to the project after completing the tutorial to see what else I can do with it.
My <AddColourForm> component assembles a <Colour> object and posts it off via an XmlHttpRequest to my API controller which in turn persists it to local storage. The submitUrl for the controller is passed in through the props. This works.
I've since tried to add the <SoftDeleteColour> component to each colourNode rendered in the <ColourList> which I intend to behave in more-or-less the same manner as the <AddColourForm> component. Each colourNode rendered in the <ColourList> has it's own delete button and I want the <SoftDeleteColour> component to take the colour.id from the selected colour and pass it to the softDelete action on the API controller so that can be handled in turn (it'll find the colour by id and append a DateDeleted to it, the API will then ignore any colours where DateDeleted != null) and the <SoftDeleteColour> component can then call loadColoursFromServer() to bring back the refreshed list from the storage. I want <SoftDeleteColour> to receive the softDeleteUrl from props in the same way that the add form does.
When I run the project in debug the softDeleteUrl is coming in as undefined and when I inspect the props in the browser it doesn't contain the softDeleteUrl. Also the "colour" is undefined so I feel like my <SoftDeleteColour> component isn't receiving the props or state. I'm new to React and struggling conceptually with props/state binding a little bit so I suspect this is the source of my problem.
How can I pass the softDeleteUrl and the properties of the colour from the <ColourList> that I am selecting for deletion to the <SoftDeleteColour> component? Do I need to call something like <SoftDeleteColour HandleDeletion=this.HandleDeletion.bind(this) /> or something?
class ColourDisplay extends React.Component {
constructor(props) {
super(props);
this.state = { data: [] };
this.handleColourSubmit = this.handleColourSubmit.bind(this);
}
loadColoursFromServer() {
const xhr = new XMLHttpRequest();
xhr.open('get', this.props.url, true);
xhr.onload = () => {
const data = JSON.parse(xhr.responseText);
this.setState({ data: data });
};
xhr.send();
}
handleColourSubmit(colour) {
const data = new FormData();
data.append('name', colour.name);
data.append('brand', colour.brand);
data.append('expiry', colour.expiry);
data.append('serialNumber', colour.serialNumber);
const xhr = new XMLHttpRequest();
xhr.open('post', this.props.submitUrl, true);
xhr.onload = () => this.loadColoursFromServer();
xhr.send(data);
}
componentDidMount() {
this.loadColoursFromServer();
}
render() {
return (
<div className="colourDisplay">
<h1>Colours</h1>
<ColourList data={this.state.data}/>
<AddColourForm onColourSubmit={this.handleColourSubmit}/>
</div>
);
}
}
class ColourList extends React.Component {
render() {
const colourNodes = this.props.data.map(colour => (
<Colour name={colour.name} key={colour.id}>
<div>Brand: {colour.brand}</div>
<div>Exp: {colour.expiry}</div>
<div>Serial #: {colour.serialNumber}</div>
<div>Date Added: {colour.dateAdded}</div>
<SoftDeleteColour />
</Colour>
));
return <div className="colourList">{colourNodes}</div>;
}
}
class SoftDeleteColour extends React.Component {
constructor(props) {
super(props)
this.state = {
colour: this.props.colour
};
}
HandleDeletion(colour) {
var xhr = new XMLHttpRequest();
var url = this.props.softDeleteUrl + colour.id;
xhr.open('DELETE', url, true);
xhr.onreadystatechange = () => {
if (xhr.status == 204) {
this.loadColoursFromServer();
}
}
xhr.send();
}
render() {
return (
<button onClick={() => { this.HandleDeletion(this.state.colour); }}>Delete</button>
)
}
}
class AddColourForm extends React.Component {
constructor(props) {
super(props);
this.state = { name: '', brand: '', expiry: '', serialNumber: '' };
this.handleNameChange = this.handleNameChange.bind(this);
this.handleBrandChange = this.handleBrandChange.bind(this);
this.handleExpiryChange = this.handleExpiryChange.bind(this);
this.handleSerialNumberChange = this.handleSerialNumberChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleNameChange(e) {
this.setState({ name: e.target.value });
}
handleBrandChange(e) {
this.setState({ brand: e.target.value });
}
handleExpiryChange(e) {
this.setState({ expiry: e.target.value });
}
handleSerialNumberChange(e) {
this.setState({ serialNumber: e.target.value })
}
handleSubmit(e) {
e.preventDefault();
const name = this.state.name.trim();
const brand = this.state.brand.trim();
const expiry = this.state.expiry.trim();
const serialNumber = this.state.serialNumber.trim();
if (!name || !brand || !expiry || !serialNumber) {
return;
}
this.props.onColourSubmit({
name: name,
brand: brand,
expiry: expiry,
serialNumber: serialNumber
})
this.setState({
name: '',
brand: '',
expiry: '',
serialNumber: ''
});
}
render() {
return (
<form className="addColourForm" onSubmit={this.handleSubmit}>
<h2>Add a colour to your list</h2>
<div>
<input
type="text"
placeholder="Colour"
value={this.state.name}
onChange={this.handleNameChange}
/>
</div>
<div>
<input
type="text"
placeholder="Brand"
value={this.state.brand}
onChange={this.handleBrandChange}
/>
</div>
<div>
<input
type="text"
placeholder="Expiry MM/YY"
value={this.state.expiry}
onChange={this.handleExpiryChange}
/>
</div>
<div>
<input
type="text"
placeholder="Serial #"
value={this.state.serialNumber}
onChange={this.handleSerialNumberChange}
/>
</div>
<input type="submit" value="Post" />
</form>
);
}
}
class Colour extends React.Component {
render() {
return (
<div className="colour">
<h2 className="colourName">{this.props.name}</h2>
{this.props.children}
</div>
);
}
}
ReactDOM.render(
<ColourDisplay
url="/colours"
submitUrl="/colours/new"
softDeleteUrl="/colours/softDelete"
/>,
document.getElementById('content')
);

Can't type in React input text field in Todo app

I am making a todo app in React.js but stuck in this part. I can not type in input field. Please help me.
import React, { Component } from 'react';
export default class AddItem extends Component {
state =
{
title: "",
done: false
}
changeTitle = (e) =>{
e.preventDefault();
this.setState = ({
title: e.target.value
});
}
addNewItem = (item) => {
item.preventDefault();
let newTask = {
title: this.state.title,
done: false
};
this.props.additem(newTask);
this.setState = ({
title: ""
});
}
render() {
return (
<div>
<form>
<input
type="text"
placeholder="add task name."
value={this.state.title}
onChange= {this.changeTitle}
/>
<button type = "button" onClick= {this.addNewItem} >submit</button>
</form>
</div>
)
}
}
this.setState is a function that is called with an object containing changes in state. The code you are using here is an assignment not a function call:
this.setState = ({
title: e.target.value // Wrong
});
Instead, call the setState function with the changes/updates in state. the changes are shallow merged and only title is updated here.
this.setState({title:e.target.value});
You will have a similar problem inside addNewItem.

React. How to populate the form after the login is completed

I have two react components(SignupDetails.js, BasicInformation.js). SignupDetails is obviously responsible to signup the user, it will get the user information from the form and submit it to the server through axios.
On the server side(backend), if the user already exist, the server will then collect the remain information, such as first name, middle name, etc and then send it back to be collected on the client side.
Back to the client side, now the remain user information which has been returned is then stored in the central store using the redux-reducers and the page is then "redirected" to BasicInformation.js
Now on the BasicInformation.js, mapStateToPros is then executed so I will do have access to the information that has been stored on the central store but then it becomes the problem: I am struggling to show the remain information. This sounds pretty simple but I tried many things on the componentDidUpdate and on the render method but without being successful.
Please find the code below and let me know if you any ideas.
import React, {Component} from 'react';
import classes from './SignUp.module.css';
import {connect} from 'react-redux'
import * as actions from '../../store/actions/index';
import Spinner from '../../components/UI/Spinner/Spinner'
class SignupDetails extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
password: ''
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
postDataHandler = () => {
const data = {
username: this.state.email,
email: this.state.email,
password: this.state.password
};
this.props.onSignupDetails(data);
}
componentDidMount() {
this.props.history.push({pathname: '/signup_details/'})
}
componentDidUpdate() {
if (this.props.signup_details_success)
this.props.history.push({pathname: '/basic_information/'})
}
render() {
let errorMessage = null;
if (this.props.error) {
errorMessage = (
<p>{this.props.signup_details_response}</p>
);
}
return (
<div>
<Spinner show={this.props.loading}/>
<div className={classes.SignUpForm}>
{errorMessage}
<h3>Take your first step.</h3>
<div>
<input
key="email"
name="email"
value={this.state.email}
onChange={this.handleInputChange}/>
</div>
<div>
<input
key="password"
name="password"
value={this.state.password}
onChange={this.handleInputChange}/>
</div>
<button className={classes.OkButton} onClick={this.postDataHandler}>Next</button>
</div>
</div>
);
}
}
const mapStateToProps = state => {
return {
signup_details: state.signup.signup_details,
signup_details_success: state.signup.signup_details_success,
signup_details_response: state.signup.signup_details_response,
loading: state.signup.loading,
error: state.signup.error
};
};
const mapDispatchToProps = dispatch => {
return {
onSignupDetails: (signup_details) => dispatch(actions.signupDetails(signup_details))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(SignupDetails);
-----
import React, {Component} from 'react';
import classes from './SignUp.module.css';
import {connect} from 'react-redux'
import * as actions from '../../store/actions/index';
import Spinner from '../../components/UI/Spinner/Spinner'
class BasicInformation extends Component {
constructor(props) {
super(props)
this.state = {
first_name: '',
middle_name: '',
last_name: '',
mobile_number: '',
fund_balance: ''
}
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
postDataHandler = () => {
const data = {
username: this.state.email,
email: this.state.email,
first_name: this.state.first_name,
middle_name: this.state.middle_name,
last_name: this.state.last_name,
mobile_number: this.state.mobile_number,
sfunds: [{balance: this.state.fund_balance}]
};
this.props.onSignupBasicInformation(data);
}
componentDidUpdate() {
if (this.props.signup_basic_information_success)
this.props.history.push({pathname: '/personal_information/'})
}
render() {
let errorMessage = null;
if (this.props.error) {
errorMessage = (
<p>{this.props.signup_basic_information_response}</p>
);
}
return (
<div>
<Spinner show={this.props.loading}/>
<div className={classes.SignUpForm}>
{errorMessage}
<h3>First we need some basic information</h3>
<div><input
key="first_name"
name="first_name"
value={this.state.first_name}
onChange={this.handleInputChange}/></div>
<div><input
key="middle_name"
name="middle_name"
value={this.state.middle_name}
onChange={this.handleInputChange}/></div>
<div><input
key="last_name"
name="last_name"
value={this.state.last_name}
onChange={this.handleInputChange}/></div>
<div><input
key="mobile_number"
name="mobile_number"
value={this.state.mobile_number}
onChange={this.handleInputChange}/></div>
<div><input
key="fund_balance"
name="fund_balance"
value={this.state.fund_balance}
onChange={this.handleInputChange}/></div>
<button className={classes.OkButton} onClick={this.postDataHandler}>Next</button>
</div>
</div>
);
}
}
const mapStateToProps = state => {
return {
signup_details_success: state.signup.signup_details_success,
signup_details_response: state.signup.signup_details_response,
signup_basic_information: state.signup.signup_basic_information,
signup_basic_information_success: state.signup.signup_basic_information_success,
signup_basic_information_response: state.signup.signup_basic_information_response,
loading: state.signup.loading,
error: state.signup.error
};
};
const mapDispatchToProps = dispatch => {
return {
onSignupBasicInformation: (basic_information) => dispatch(actions.signupBasicInformation(basic_information))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(BasicInformation);
In case someone wonder, I managed to solve this problem through componentDidMount to set the local state.
componentDidMount(){
if(this.props.smsf_member_details) {
this.setState({
first_name: this.props.smsf_member_details.first_name,
last_name: this.props.smsf_member_details.last_name,
middle_name: this.props.smsf_member_details.middle_name,
});
}
}

FormValidation with Button State

In my React app, I have a component call <ComingSoonForm/> Inside that, I have a TextInputField. If the Email valid, the Notify-Button is able. If the Email is invalid, the Notify-Button is disabled.
Here is my Component File:
import React, { Component } from "react";
import { TextInputField, toaster, Button, } from "evergreen-ui";
import Box from 'ui-box';
import { validateEmail } from "../FormValidation/FormValidator";
class ComingSoonForm extends Component {
constructor(props) {
super(props);
this.state = {
emailErr: {
status: true,
value: ""
},
email: "",
isDisabled: true,
};
this.handleSubmit = this.handleSubmit.bind(this);
this.checkFormStatus = this.checkFormStatus.bind(this);
}
handleEmailInput = e => {
const email = e.target.value;
this.setState({ email: email});
console.log(this.state.email);
this.checkFormStatus();
};
handleSubmit() {
if (this.checkFormStatus()) {
alert("Form is OK")
}
}
checkFormStatus() {
// form validation middleware
const { email } = this.state;
const emailErr = validateEmail(email);
if (!emailErr.status) {
this.setState({isDisabled:false})
return true;
} else {
this.setState({
emailErr,
});
return false;
}
}
render() {
return (
<div>
<Box className="welcomePageWelcomeInnerLoginButton">
<TextInputField
marginTop={15}
width={200}
onChange={this.handleEmailInput}
value={this.state.email}
type="email"
placeholder="Your email-address"
inputHeight={40}
/>
</Box>
<Button height="40" appearance="primary" marginBottom={5} className="welcomePageWelcomeInnerLoginButtonWidth" disabled={this.state.isDisabled} onClick={this.handleSubmit}>Notify Me</Button>
</div>
);
}
}
export default ComingSoonForm;
But this case doesn't work correctly. So when the command console.log(this.state.email) in the handleEmailInput Function run, I get the following data in the console:
I type one letter (t) and I get:
//ComingSoonForm.js:25
I type a second letter (t) and I get:
t //ComingSoonForm.js:25
t //FormValidator.js:10
Why do I have to enter two letters in order for one to appear in the console?
setState is asynchronous, you can pass a callback method as a second parameter like this:
handleEmailInput = e => {
const email = e.target.value;
this.setState({ email: email }, () => console.log(this.state.email));
this.checkFormStatus();
};

How to check form is valid or not in react + material?

Is there any way to know that form is valid or not in react + material ui .I am using react material in my demo .I have three field in my form all are required . I want to check on submit button that form is valid or not
Here is my code
https://codesandbox.io/s/w7w68vpjj7
I don't want to use any plugin
submitButtonHandler = () => {
console.log("error");
console.log(this.state.form);
};
render() {
const { classes } = this.props,
{ form } = this.state;
return (
<div className={classes.searchUser__block}>
<SearchForm
handleInput={this.handleInputFieldChange}
submitClick={this.submitButtonHandler}
form={form}
/>
</div>
);
}
You would have to manually do that verification if you don't want to use any library. Material-ui does not have any validation built in as per their documentation. BUT it does give you some tools for that like errorMessage to text fields for example. You just have to play with it
Example:
class PhoneField extends Component
constructor(props) {
super(props)
this.state = { errorText: '', value: props.value }
}
onChange(event) {
if (event.target.value.match(phoneRegex)) {
this.setState({ errorText: '' })
} else {
this.setState({ errorText: 'Invalid format: ###-###-####' })
}
}
render() {
return (
<TextField hintText="Phone"
floatingLabelText="Phone"
name="phone"
errorText= {this.state.errorText}
onChange={this.onChange.bind(this)}
/>
)
}
}
a bit outdated example i had laying around
Form validation can be pretty complex, so I'm pretty sure you'll end up using a library. As for now, to answer your question, we need to think about form submission flow. Here is a simple example:
"Pre-submit"
Set isSubmitting to true
Proceed to "Validation"
"Validation"
Run all field-level validations using validationRules
Are there any errors?
Yes: Abort submission. Set errors, set isSubmitting to false
No: Proceed to "Submission"
"Submission"
Proceed with running your submission handler (i.e.onSubmit or handleSubmit)
Set isSubmitting to false
And some minimal implementation would be something like:
// ...imports
import validateForm from "../helpers/validateForm";
import styles from "./styles";
import validationRules from "./validationRules";
const propTypes = {
onSubmit: PropTypes.func.isRequired,
onSubmitError: PropTypes.func.isRequired,
initialValues: PropTypes.shape({
searchValue: PropTypes.string,
circle: PropTypes.string,
searchCriteria: PropTypes.string
})
};
const defaultProps = {
initialValues: {}
};
class SearchForm extends Component {
constructor(props) {
super(props);
this.validateForm = validateForm.bind(this);
this.state = {
isSubmitting: false,
values: {
searchValue: props.initialValues.searchValue || "",
circle: props.initialValues.circle || "",
searchCriteria: props.initialValues.searchCriteria || ""
},
...this.initialErrorState
};
}
get hasErrors() {
return !!(
this.state.searchValueError ||
this.state.circleError ||
this.state.searchCriteriaError
);
}
get initialErrorState() {
return {
searchValueError: null,
circleError: null,
searchCriteriaError: null
};
}
handleBeforeSubmit = () => {
this.validate(this.onValidationSuccess);
};
validate = (onSuccess = () => {}) => {
this.clearErrors();
this.validateForm(validationRules)
.then(onSuccess)
.catch(this.onValidationError);
};
onValidationSuccess = () => {
this.setState({ isSubmitting: true });
this.props
.onSubmit(this.state.values)
.catch(this.props.onSubmitError)
.finally(() => this.setState({ isSubmitting: false }));
};
onValidationError = errors => {
this.setState({ ...errors });
};
clearErrors = () => {
this.setState({ ...this.initialErrorState });
};
updateFormValue = fieldName => event => {
this.setState(
{
values: { ...this.state.values, [fieldName]: event.target.value }
},
() => this.validate()
);
};
render() {
// ...
}
}
SearchForm.propTypes = propTypes;
SearchForm.defaultProps = defaultProps;
export default withStyles(styles)(SearchForm);
As you can see, if submission flow will grow larger (for example touching inputs, passing errors, etc), the of amount of complexity inside of a component will significantly grow as well. That is why it's more preferable to use a well-maintained library of choice. Formik is my personal preference at the moment.
Feel free to check out updated codesandbox. Hope it helps.
Hi Joy I've made desirable form validation if required fields are empty.
Here is the updated codesandbox: https://codesandbox.io/s/50kpk7ovz4

Resources