I have some issue using asyncBlurFields in redux form, it just doesn't response,
container:
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import SupplierEditForm from '../../components/suppliers/SupplierEditForm'
import { reduxForm, change } from 'redux-form'
import { createSupplierRequest, updateSupplierRequest, fetchSupplierInfoRequest, validateSupplierRequest } from '../../api/suppliers'
import { resetSupplierForm, supplierFormSubmitSuccess } from '../../actions/SuppliersActions'
class SuppliersEditView extends Component {
constructor(props, context) {
super(props, context);
this.state = {isSubmitting: false}
}
componentWillMount() {
this.props.dispatch(resetSupplierForm())
}
componentDidMount() {
if(this.props.params.supplier_id) {
this.props.dispatch(fetchSupplierInfoRequest(this.props.params.supplier_id))
}
}
componentWillReceiveProps(nextProps) {
if(nextProps.supplier.isAction==true) {
if(!this.props.params.supplier_id) {
this.context.router.push('/suppliers/edit/'+nextProps.supplier.supplier_id)
} else {
this.props.dispatch(fetchSupplierInfoRequest(nextProps.supplier.supplier_id))
}
this.setState({isSubmitting:true})
setTimeout(() => {
this.hideStatus()
this.props.dispatch(supplierFormSubmitSuccess())
}, 1500)
}
}
hideStatus() {
this.setState({isSubmitting:false})
}
render() {
let pageHeader
if(this.props.fields.company_name.value) {
pageHeader = <h1 className="page-header">Suppliers - { this.props.fields.company_name.value }</h1>
}
else {
pageHeader = <h1 className="page-header">Suppliers</h1>
}
return (
<div className="container-fluid">
{pageHeader}
<SupplierEditForm
fields={this.props.fields}
handleSubmit={this.props.handleSubmit}
dispatchSupplier={this.props.dispatchSupplier.bind(this)}
supplier={this.props.supplier.payload}
isSubmitting={this.state.isSubmitting}
dispatchFieldChange={this.props.dispatchFieldChange}
supplier_id={this.props.params.supplier_id}
/>
</div>
)
}
}
const validateSupplier = (values, dispatch) => {
console.log('hi')
return new Promise((resolve, reject) => {
dispatch(validateSupplierRequest(values))
.then((response) => {
console.log(response)
});
})
}
const mapStateToProps = (state) => ({
supplier: state.suppliers.supplierInfo,
initialValues: state.suppliers.supplierInfo.payload
})
const mapDispatchToProps = (dispatch, props) => ({
dispatchSupplier: (values) => {
!props.params.supplier_id ? dispatch(createSupplierRequest(values)) : dispatch(updateSupplierRequest(values, props.params.supplier_id))
},
dispatchFieldChange: (field, value) => {
dispatch(change('SupplierEditForm',field,value))
}
})
SuppliersEditView.propTypes = {
asyncValidating: PropTypes.string.isRequired,
fields: PropTypes.object.isRequired,
resetForm: PropTypes.func.isRequired,
handleSubmit: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
}
SuppliersEditView.contextTypes = {
router: PropTypes.object
}
SuppliersEditView = reduxForm({
form: 'SupplierEditForm',
fields: ['company_logo','company_name', 'business_registration_no', 'mailing_address', 'billing_address', 'phone', 'email', 'fax', 'contact_person', 'contact_phone', 'contact_email', 'comments'],
asyncValidate: validateSupplier,
asyncBlurFields:['business_registration_no']
})(SuppliersEditView)
export default connect(mapStateToProps, mapDispatchToProps)(SuppliersEditView)
component:
import React, { Component } from 'react'
import { Link } from 'react-router'
import ReactDOM, { findDOMNode } from 'react-dom';
import { config } from '../../config'
import _ from 'lodash'
class SupplierEditForm extends Component {
constructor(props, context) {
super(props, context)
this.state = {
file: null,
imagePreviewUrl: null
}
}
handleImageChange(e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
this.setState({
file: file,
imagePreviewUrl: reader.result
})
}
this.props.dispatchFieldChange(['company_logo'],file)
reader.readAsDataURL(file)
}
triggerImageUpload() {
ReactDOM.findDOMNode(this.refs.upload).click()
}
render () {
const { fields: { company_logo, company_name, business_registration_no, mailing_address, billing_address, phone, email, fax, contact_person, contact_phone, contact_email, comments }, handleSubmit, isSubmitting } = this.props
let imageSection
if(this.state.imagePreviewUrl) {
imageSection = <img src={this.state.imagePreviewUrl} width="100" onClick={this.triggerImageUpload.bind(this)}/>
} else if (_.isEmpty(this.props.supplier) || _.isNull(this.props.supplier.filename)){
imageSection = <div className="img-placeholder" onClick={this.triggerImageUpload.bind(this)}></div>
} else if (!_.isNull(this.props.supplier.filename) || !_.isEmpty(this.props.supplier)){
imageSection = <img src={config.FILE_DIR + this.props.supplier.filename} width="100" onClick={this.triggerImageUpload.bind(this)}/>
}
return (
<form onSubmit={handleSubmit(this.props.dispatchSupplier)} >
<button type="submit" disabled={isSubmitting} className="btn btn-primary mr8">
{
isSubmitting == true ?
<i className="fa fa-circle-o-notch fa-spin fa-fw"></i>
:
'Save'
}
</button>
<Link to="/suppliers" className="btn btn-secondary">Back</Link>
<div className="row">
{
isSubmitting ?
<div className="form-overlay"/>
: null
}
<div className="col-md-6">
<h2 className="mb24">Supplier details</h2>
<div className="form-group">
<label>Company logo</label>
<div className="col-md-12">
{imageSection}
</div>
<input type="file" ref="upload" className="col-xs-12 mb24 hide" {...company_logo} value={null} onChange={this.handleImageChange.bind(this)} />
</div>
<div className="form-group">
<label>Company name</label>
<input type="text" className="col-xs-12" {...company_name} required/>
</div>
<div className="form-group">
<label>Business registration no.</label>
<input type="text" className="col-xs-12" {...business_registration_no} required/>
</div>
<div className="form-group">
<label>Mailing address</label>
<input type="text" className="col-xs-12" {...mailing_address} required/>
</div>
<div className="form-group">
<label>Billing address</label>
<input type="text" className="col-xs-12" {...billing_address} required/>
</div>
<div className="form-group">
<label>Comments</label>
<textarea type="text" className="col-xs-12" {...comments} required></textarea>
</div>
</div>
<div className="col-md-6">
<h2 className="mb24">Contact details</h2>
<div className="form-group">
<label>Phone</label>
<input type="text" className="col-xs-12" {...phone} required/>
</div>
<div className="form-group">
<label>Fax</label>
<input type="text" className="col-xs-12" {...fax} required/>
</div>
<div className="form-group">
<label>Email</label>
<input type="email" className="col-xs-12" {...email} required/>
</div>
<div className="form-group">
<label>Contact person</label>
<input type="text" className="col-xs-12" {...contact_person} required/>
</div>
<div className="form-group">
<label>Contact phone</label>
<input type="text" className="col-xs-12" {...contact_phone} required/>
</div>
<div className="form-group">
<label>Contact email</label>
<input type="email" className="col-xs-12" {...contact_email} required/>
</div>
</div>
</div>
</form>
)
}
}
export default SupplierEditForm
However, whenever form is submitted, business_registration_no is suppose to respond on input lost focus, but it does not respond, have been trying for whole day. The weird thing is instead of firing this.props.dispatchSupplier when handleSubmit is invoked, it fires asyncValidate. Is there anything wrong in my code? Desperate for help!!
yep. need to use the Field-component and then also pass onBlur to that component..
like so :
https://github.com/erikras/redux-form/issues/1834
or so:
render() {
const { input: { value, onChange, onBlur }, meta: { touched, error } } = this.props
return (
<div>
<div className="example-class">
<input
type="tel"
className={this.inputFormClass(touched, error)}
autoComplete="on"
onChange={this.setPhoneNumber.bind(this)}
placeholder="some Placeholder"
onBlur={() => onBlur(value)}
/>
</div>
{this.showErrorMessage(touched, error)}
</div>
)
}
Related
I can't find the solution to this error in my code every time I try to type something in my input field. TypeError: Cannot read property 'name' of undefined
but I've done like the answer in the following post https://stackoverflow.com/a/57519847/16568705 still not work
Here is all code
MultiStepForm.js
import { useForm, useStep } from "react-hooks-helper";
import React from "react";
import { LaporanPolisi } from "./stepForm/LaporanPolisi";
const defaultData = {
laporanPolisi: {
nomorLp: "",
jenisKelamin: 0,
tanggalLp: "",
kerugian: 0,
uraianSingkat: "",
pasalDilanggar: [
{
undangUndang: "",
pasal: ""
}
]
},
pelapor: [],
saksi: [],
korban: [],
terlapor: [],
barangBukti: [],
tkp: {
kodeProvinsi: "",
kodeKabupaten: "",
kodeKecamatan: "",
kodeKelurahan: "",
kodeRT: "",
kodeRW: ""
}
}
const steps = [
{ id: "laporanPolisi" },
{ id: "pelapor" },
{ id: "saksi" },
{ id: "korban" },
{ id: "terlapor" },
{ id: "barangBukti" },
{ id: "tkp" },
{ id: "submit" }
]
export const MultiStepForm = () => {
const [formData, setForm] = useForm(defaultData);
const { step, navigation } = useStep({
steps,
initialStep: 0,
});
const props = { formData, setForm, navigation };
switch (step.id) {
case "laporanPolisi":
return <LaporanPolisi {...props} />;
case "pelapor":
return "Pelapor";
case "saksi":
return "Saksi";
case "korban":
return "Korban";
case "terlapor":
return "Terlapor";
case "barangBukti":
return "Barang Bukti";
case "tkp":
return "TKP";
case "submit":
return "Submit";
default:
return <LaporanPolisi {...props} />;
}
};
LaporanPolisi.js
import React from 'react';
export const LaporanPolisi = ({ formData, setForm, navigation }) => {
const {
laporanPolisi
} = formData;
const handleChange = e => {
const { name, value } = e.target;
console.log(name)
setForm(prevState => ({
...prevState,
laporanPolisi: {
...prevState.laporanPolisi,
[name]: value
}
}));
};
return (
<div className="card">
<div className="card-header">
<h4>Laporan Polisi</h4>
</div>
<div className="card-body">
<div className="row">
<div className="col-md-6">
<div className="form-group">
<label htmlFor="nomorLp">Nomor Laporan</label>
<input onChange={handleChange} id="nomorLp"
placeholder="Nomor Laporan" type="text" className="form-control" name="nomorLp" value={laporanPolisi.nomorLp} />
</div>
</div>
<div className="col-md-6">
<div className="form-group">
<label htmlFor="jenisKelamin">Jenis Kelamin</label>
<select onChange={handleChange} value={laporanPolisi.jenisKelamin} id="jenisKelamin" name="jenisKelamin" className="custom-select">
<option value={0}>Laki-Laki</option>
<option value={1}>Perempuan</option>
</select>
</div>
</div>
{/* <input placeholder="Tanggal Laporan" type="text" className="form-control" name="nomorLp" value={jenisKelamin}></input>
<input placeholder="Kerugian" type="text" className="form-control" name="nomorLp" value={nomorLp}></input>
<input placeholder="Uraian Singkat" type="text" className="form-control" name="nomorLp" value={nomorLp}></input>
<input placeholder="Nomor Laporan" type="text" className="form-control" name="nomorLp" value={nomorLp}></input> */}
</div>
</div>
<pre>
<code>
{JSON.stringify(formData.laporanPolisi)}
</code>
</pre>
</div>
)
}
error Image:
https://imgur.com/a/JC89ykW
thanks before sorry for my bad english.
All react components have to return a component, for example: ...
In your MultiStepForm.js there are only 2 cases meet this requirement.
And this is the way I dealt with input, if you want to update setForm, you can add it in hanldeChange:
export default function BasicExample({ formData, setForm, navigation }) {
const [input1, setInput1] =useState('');
const [input2, setInput2] =useState('');
const handleChange = e => {
e.preventDefault()
console.log(input1)
console.log(input2)
};
return (
<form onSubmit={handleChange}>
<div className="col-md-6">
<div className="form-group">
<label htmlFor="nomorLp">Nomor Laporan</label>
<input onChange={e => setInput1(e.target.value)} id="nomorLp"
placeholder="Nomor Laporan" type="text" className="form-control" name="nomorLp" value={input1} />
</div>
</div>
<div className="col-md-6">
<div className="form-group">
<label htmlFor="jenisKelamin">Jenis Kelamin</label>
<select onChange={e => setInput2(e.target.value)} value={input2} id="jenisKelamin" name="jenisKelamin" className="custom-select">
<option value={0}>Laki-Laki</option>
<option value={1}>Perempuan</option>
</select>
</div>
</div>
<button type="submit"> Summit</button>
</form>
);
}
Resolved
i need to define name like this
https://imgur.com/POGiQ5z
in section Nested Object at https://github.com/revelcw/react-hooks-helper
and then, this is my fullcode after change:
LaporanPolisi.js
import React from 'react';
export const LaporanPolisi = ({ formData, setForm, navigation }) => {
const {
laporanPolisi
} = formData;
const handleSubmit = e => {
e.preventDefault();
};
return (
<div className="card">
<div className="card-header">
<h4>Laporan Polisi</h4>
</div>
<div className="card-body">
<form onSubmit={handleSubmit}>
<div className="row">
<div className="col-md-6">
<div className="form-group">
<label htmlFor="nomorLp">Nomor Laporan</label>
<input onChange={setForm} id="nomorLp"
placeholder="Nomor Laporan" type="text" className="form-control" name="laporanPolisi.nomorLp" value={laporanPolisi.nomorLp} />
</div>
</div>
<div className="col-md-6">
<div className="form-group">
<label htmlFor="jenisKelamin">Jenis Kelamin</label>
<select onChange={setForm} id="jenisKelamin" name="laporanPolisi.jenisKelamin" className="custom-select" value={laporanPolisi.jenisKelamin}>
<option value={0}>Laki-Laki</option>
<option value={1}>Perempuan</option>
</select>
</div>
</div>
<div className="col-md-6">
<button className="btn btn-primary" onClick={() => navigation.previous()} type="button">Previous</button>
</div>
<div className="col-md-6">
<button className="btn btn-primary" onClick={() => navigation.next()} type="button">Next</button>
</div>
{/* <input placeholder="Tanggal Laporan" type="text" className="form-control" name="nomorLp" value={jenisKelamin}></input>
<input placeholder="Kerugian" type="text" className="form-control" name="nomorLp" value={nomorLp}></input>
<input placeholder="Uraian Singkat" type="text" className="form-control" name="nomorLp" value={nomorLp}></input>
<input placeholder="Nomor Laporan" type="text" className="form-control" name="nomorLp" value={nomorLp}></input> */}
</div>
</form>
</div>
<pre>
<code>
{JSON.stringify(laporanPolisi)}
</code>
</pre>
</div>
)
}
thanks everyone for answering my question
I am facing this when I am trying to set form error object. Basically, I want to show the errors below each input field. In response, I am getting an array of objects how do I set to my error object?
Error - Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
import axios from "axios";
import React, { useState, useEffect, useCallback } from "react";
import { Link } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { register } from "../actions/userActions";
const Register = () => {
const [countriesList, setCountriesList] = useState("");
const [userRegistration, setUserRegistration] = useState({
firstName: "",
lastName: "",
email: "",
password: "",
fullAddress: "",
city: "",
zipCode: "",
country: "",
phone: "",
terms: true,
});
const [userRegistrationError, setUserRegistrationError] = useState({
firstNameError: "",
lastNameError: "",
emailError: "",
passwordError: "",
fullAddressError: "",
cityError: "",
zipCodeError: "",
countryError: "",
phoneError: "",
termsError: "",
});
const dispatch = useDispatch();
const userRegister = useSelector((state) => state.userRegister);
const { loading, errors, success } = userRegister;
useEffect(() => {
const countries = async () => {
try {
const { data } = await axios.get(
`https://restcountries.eu/rest/v2/all`
);
setCountriesList(data);
} catch (err) {
console.error(err);
}
};
countries();
}, []);
useEffect(() => {
const handleErrors = (errors) => {
errors.map((error) => {
if (error.param === "firstname") {
setUserRegistrationError({
...userRegistrationError,
firstNameError: error.msg,
});
}
if (error.param === "email") {
setUserRegistrationError({
...userRegistrationError,
emailError: error.msg,
});
}
return null;
});
};
if (errors) {
handleErrors(errors);
}
}, [errors, setUserRegistrationError]);
const handleChange = (e) => {
const name = e.target.name;
const value = e.target.value;
setUserRegistration({ ...userRegistration, [name]: value });
};
const handleChkChange = (e) => {
const checked = e.target.checked;
console.log(checked);
setUserRegistration({ ...userRegistration, terms: checked });
};
const handleSubmit = (e) => {
e.preventDefault();
try {
dispatch(register());
} catch (error) {
console.error(error);
}
};
return (
<div className="form_container">
<form action="" onSubmit={handleSubmit}>
<div className="row no-gutters">
<div className="col-6 pr-1">
<div className="form-group">
<div className="form-group">
<input
type="text"
name="firstName"
className="form-control"
placeholder="First Name*"
value={userRegistration.firstName}
onChange={handleChange}
/>
<p className="form-vald-error">
{userRegistrationError.firstNameError &&
userRegistrationError.firstNameError}
</p>
</div>
</div>
</div>
<div className="col-6 pr-1">
<div className="form-group">
<input
type="text"
className="form-control"
name="lastName"
placeholder="Last Name*"
value={userRegistration.lastName}
onChange={handleChange}
/>
<p className="form-vald-error">
{userRegistrationError.lastNameError &&
userRegistrationError.lastNameError}
</p>
</div>
</div>
</div>
<hr />
<div className="private box">
<div className="row no-gutters">
<div className="col-6 pr-1">
<div className="form-group">
<input
type="email"
className="form-control"
name="email"
id="email_2"
placeholder="Email*"
value={userRegistration.email}
onChange={handleChange}
/>
<p className="form-vald-error">
{userRegistrationError.emailError &&
userRegistrationError.emailError}
</p>
</div>
</div>
<div className="col-6 pl-1">
<div className="form-group">
<input
type="password"
className="form-control"
name="password"
id="password_in_2"
placeholder="Password*"
value={userRegistration.password}
onChange={handleChange}
/>
<p className="form-vald-error">
{userRegistrationError.passwordError &&
userRegistrationError.passwordError}
</p>
</div>
</div>
<div className="col-12">
<div className="form-group">
<input
type="text"
name="fullAddress"
className="form-control"
placeholder="Full Address*"
value={userRegistration.fullAddress}
onChange={handleChange}
/>
<p className="form-vald-error">
{userRegistrationError.fullAddressError &&
userRegistrationError.fullAddressError}
</p>
</div>
</div>
</div>
{/* /row */}
<div className="row no-gutters">
<div className="col-6 pr-1">
<div className="form-group">
<input
type="text"
className="form-control"
placeholder="City*"
name="city"
value={userRegistration.city}
onChange={handleChange}
/>
<p className="form-vald-error">
{userRegistrationError.cityError &&
userRegistrationError.cityError}
</p>
</div>
</div>
<div className="col-6 pl-1">
<div className="form-group">
<input
type="text"
className="form-control"
placeholder="Postal Code*"
name="zipCode"
value={userRegistration.zipCode}
onChange={handleChange}
/>
<p className="form-vald-error">
{userRegistrationError.zipCodeError &&
userRegistrationError.zipCodeError}
</p>
</div>
</div>
</div>
{/* /row */}
<div className="row no-gutters">
<div className="col-6 pr-1">
<div className="form-group">
<div className="custom-select-form">
<select
className="wide add_bottom_10 form-control"
name="country"
id="country"
value={userRegistration.country}
onChange={handleChange}
>
<option>Country*</option>
{countriesList &&
countriesList.map((country) => (
<option
key={country.alpha2Code}
value={country.alpha2Code}
>
{country.name}
</option>
))}
</select>
<p className="form-vald-error">
{userRegistrationError.countryError &&
userRegistrationError.countryError}
</p>
</div>
</div>
</div>
<div className="col-6 pl-1">
<div className="form-group">
<input
type="text"
className="form-control"
placeholder="Telephone *"
name="phone"
value={userRegistration.phone}
onChange={handleChange}
/>
<p className="form-vald-error">
{userRegistrationError.phoneError &&
userRegistrationError.phoneError}
</p>
</div>
</div>
</div>
{/* /row */}
</div>
<hr />
<div className="form-group">
<label className="container_check">
Accept <Link to="#0">Terms and conditions</Link>
<input
type="checkbox"
name="terms"
checked={userRegistration.terms}
onChange={handleChkChange}
/>
<span className="checkmark" />
<p className="form-vald-error">
{userRegistrationError.termsError &&
userRegistrationError.termsError}
</p>
</label>
</div>
<div className="text-center">
<input
type="submit"
defaultValue="Register"
className="btn_1 full-width"
/>
</div>
</form>
</div>
);
};
export default Register;
your effect depends on userRegistrationError which is an object, reference based. Each time useEffect runs,setUserRegistrationError
creates a new object reference, which leads to an infinite loop since references won't be the same as the previous one.
One approach to avoid this issue and keep the right references, is to pass a callback function to setUserRegistrationError instead than a value. This way userRegistrationError is no longer a dependency, it will be an argument to your function instead:
useEffect(() => {
const handleErrors = (errors) => {
errors.forEach((error) => {
if (error.param === "firstName") {
// here you pass a callback function instead, and userRegistrationError is no longer a dependency
// and returns the next state as expected
setUserRegistrationError(userRegistrationError => ({
...userRegistrationError,
firstNameError: error.msg,
}));
}
if (error.param === "email") {
setUserRegistrationError(userRegistrationError => ({
...userRegistrationError,
emailError: error.msg,
}));
}
});
};
if (errors) {
handleErrors(errors);
}
}, [errors, setUserRegistrationError]);
You have a problem with the second useEffect, the first time you update your state userRegistrationError, the component re-rendered and re-executed the useeffect because the dependency userRegistrationError has changed and the process gets repeated again because the state gets updated every render.
useEffect(() => {
const handleErrors = (errors) => {
errors.map((error) => {
if (error.param === "firstname") {
setUserRegistrationError({
...userRegistrationError,
firstNameError: error.msg,
});
}
if (error.param === "email") {
setUserRegistrationError({
...userRegistrationError,
emailError: error.msg,
});
}
return null;
});
};
if (errors) {
handleErrors(errors);
}
}, [errors, setUserRegistrationError ]); //replace userRegistrationError by setUserRegistrationError
This is my jsx for the form
import React, { Component } from "react";
import { createUser } from "../HTTPRequests";
import PhoneInput from "react-phone-number-input";
class UserRegForm extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
secondPassword: "",
username: "",
phone: "",
current: 0
};
this.handleEmail = this.handleEmail.bind(this);
this.handlePassword = this.handlePassword.bind(this);
this.handleSecondPassword = this.handleSecondPassword.bind(this);
this.handleUsername = this.handleUsername.bind(this);
this.renderSecondPassword = this.renderSecondPassword.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handlePhone = this.handlePhone.bind(this);
}
handleEmail(event) {
this.setState({ email: event.target.value });
}
handlePassword(event) {
this.setState({ password: event.target.value });
}
handleSecondPassword(event) {
this.setState({ secondPassword: event.target.value });
}
handleUsername(event) {
this.setState({ username: event.target.value });
}
handlePhone(phone) {
this.setState({ phone: phone.value });
}
renderSecondPassword() {
var classN;
if (
this.state.secondPassword.length === 0 ||
this.state.secondPassword === this.state.password
) {
classN = "form-control";
} else {
classN = "form-control is-invalid";
}
return (
<div className="form-group">
<label htmlFor="InputPassword2">Introduza novamente a Password</label>
<input
onKeyDown={this.handleKeyDown}
onChange={this.handleSecondPassword}
type="password"
className={classN}
id="InputPassword2"
/>
</div>
);
}
handleKeyDown(event) {
if (event.key === "Enter") {
this.handleSubmit();
}
}
handleSubmit() {
createUser(this.state.email, this.state.password, this.state.username).then(
function(r) {
console.log(r);
}
);
}
render() {
return (
<div className="position-relative m-4">
<form>
<div className="form-group">
<label htmlFor="exampleInputUsername">Nome Completo</label>
<input
onKeyDown={this.handleKeyDown}
onChange={this.handleUsername}
type="username"
className="form-control"
id="exampleInputUsername"
/>
</div>
<div className="form-group">
<label htmlFor="exampleInputEmail1">E-mail</label>
<input
onKeyDown={this.handleKeyDown}
onChange={this.handleEmail}
type="email"
className="form-control"
id="exampleInputEmail1"
aria-describedby="emailHelp"
/>
<small id="emailHelp" className="form-text text-muted">
Nunca partilharemos o seu e-mail com ninguém.
</small>
</div>
<PhoneInput
placeholder="Enter phone number"
value={this.state.phone}
onChange={phone => this.handlePhone({ phone })}
/>
<div className="form-group">
<label htmlFor="InputPassword1">Password</label>
<input
onKeyDown={this.handleKeyDown}
onChange={this.handlePassword}
type="password"
className="form-control"
id="InputPassword1"
/>
</div>
{this.renderSecondPassword()}
<button
type="button"
className="btn btn-primary"
onClick={this.handleSubmit}
>
Submit
</button>
</form>
</div>
);
}
}
export default UserRegForm;
And this is the result...
as you can see the flag just expands to the whole screen.
I have programming experience (C and java), but just started learning HTML and React... So i'm still a bit lost. do I have to wrap the phone number component in something so it behaves? According to documentation the flag should be to the left of the input and not below
Any help is very appreciated
As someone who just encountered the same issue as OP after an update, the fix was very simple:
import 'react-phone-number-input/style.css'
According to last version of the docs : https://github.com/catamphetamine/react-phone-number-input
This is my SearchForm.js, handleKeywordsChange must handle input keywords changes
import React from 'react';
import ReactDOM from 'react-dom';
class SearchForm extends React.Component {
constructor(props) {
super(props)
this.state = {
keywords: '',
city: '',
date: ''
}
//this.handleChange = this.handleChange.bind(this)
//this.handleSubmit = this.handleSubmit.bind(this)
this.handleKeywordsChange = this.handleKeywordsChange.bind(this);
}
handleKeywordsChange(e) {
console.log(1);
this.setState({
value: e.target.value
});
}
render() {
return (
<form className='form search-form' onSubmit={this.handleSubmit}>
<div className="form-row">
<div className="form-group col-md-5">
<label htmlFor="keywords">Keywords</label>
<input type="text" className="form-control" name="keywords" id="keywords" placeholder="Keywords" onChange={this.handleKeywordsChange} value={this.state.keywords} />
</div>
<div className="form-group col-md-5">
<label htmlFor="city">City</label>
<input type="text" className="form-control" name="city" id="city" placeholder="City" onChange={this.handleChange} value={this.state.city} />
</div>
<div className="form-group col-md-2">
<label htmlFor="date">Date</label>
<select className="form-control" name="date" id="date" onChange={this.handleChange} value={this.state.date}>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
</div>
<div className="form-row">
<div className="form-group col-md-12">
<input id='formButton' className='btn btn-primary' type='submit' placeholder='Send' />
</div>
</div>
</form>
)
}
}
export { SearchForm }
The problem is input keywords doesn't change its value when I'm typing. What's wrong?
Make a common function for changing the state for input values.
handleInputChange(e) {
this.setState({
[e.target.name]: e.target.value
});
}
Make sure you mention name in every input tag. e.g:
<input name="someUniqueName" value={this.state.someState} onChange={this.handleInputChange} />
React Hooks makes this so much easier!!!
import React, {useState} from 'react'
function SearchForm () {
const [input, setInput] = useState("")
return (
<div className="SearchForm">
<input
value={input}
onChange={(e) => setInput(e.target.value)} />
</div>
)
}
It should be :
this.setState({
keywords: e.target.value
});
Your handleKeywordsChange function sets the state value whereas you are using this.state.keywords as value for input
handleKeywordsChange(e) {
console.log(1);
this.setState({
keywords: e.target.value
});
}
class InputKeywordCheck {
state = {
email: '',
}
handleInputChange (e) {
const {name, value } = e.target;
this.setState({[name]: value});
}
render() {
return (
<input name="email" value={this.state.email} onChange={this.handleInputChange} />
)
} }
I believe that you need to do something like this:
handleKeyWordsChange (e) {
this.setState({[e.target.name]: e.target.value});
}
I am pretty new to react/redux I am pretty confused with this simple form.My error state is always undefined eventhough I am getting the error data from node js server Without error data I can't set my state.
routes/users.js
import express from 'express';
import Validator from 'validator';
import isEmpty from 'lodash/isEmpty'
let router = express.Router();
function ValidateInput(data) {
let errors = {};
if(isEmpty(data.email)){
errors.email = 'This fiels is required'
}
if(!Validator.isEmail(data.email)){
errors.email = "Email is in Valid"
}
if(isEmpty(data.password)){
errors.password = 'This fiels is required'
}
if(isEmpty(data.passwordConfirmation)){
errors.passwordConfirmation = 'This fiels is required'
}
if(!Validator.equals(data.password,data.passwordConfirmation)){
errors.passwordConfirmation = "Password Must Macthc"
}
if(isEmpty(data.timezone)){
errors.timezone = 'This fiels is required'
}
return{
errors,
isValid:isEmpty(errors)
}
}
router.post('/',(req,res) => {
console.log(req)
const {errors,isValid} = ValidateInput(req.body);
if(!isValid){
res.status(400).json(errors)
}
});
export default router
SignupForm.js
import React from 'react';
import timezones from '../../data/timezone';
import map from 'lodash/map';
class SignupForm extends React.Component {
constructor(props){
super(props);
this.state = {
username:'',
email:'',
password:'',
passwordConfirmation:'',
timezone:'',
errors:{}
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this)
}
onChange(e){
this.setState({ [e.target.name]:e.target.value })
}
onSubmit(e){
e.preventDefault();
this.setState({ errors:{} });
this.props.userSignupRequest(this.state).then(function (data) {
console.log(data)//Nothing
// this.setState({
// errors:data
// })
})
}
render(){
console.log(this.state)
const options = map(timezones,(val,key) =>
<option key={val} value={val}>{key}</option>
);
return(
<form onSubmit={this.onSubmit}>
<h1>Join our community</h1>
<div className="form-group">
<label className="control-label">Username</label>
<input
type="text"
name="username"
className="form-control"
value={this.state.username}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label className="control-label">Email</label>
<input
type="text"
name="email"
className="form-control"
value={this.state.email}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label className="control-label">Password</label>
<input
type="password"
name="password"
className="form-control"
value={this.state.password}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label className="control-label">passwordConfirmation</label>
<input
type="password"
name="passwordConfirmation"
className="form-control"
value={this.state.passwordConfirmation}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label className="control-label">Time Zone</label>
<select
className="form-control"
name="timezone"
onChange={this.onChange}
value={this.state.timezone}
>
<option value="" disabled>Choose Your Timezone</option>
{options}
</select>
</div>
<div className="form-group">
<button className="btn btn-primary btn-lg">
SignUp
</button>
</div>
</form>
)
}
}
SignupForm.propTypes ={
userSignupRequest:React.PropTypes.func.isRequired
};
export default SignupForm
You need to use catch... so
onSubmit(e){
e.preventDefault();
this.setState({ errors:{} });
this.props.userSignupRequest(this.state)
.then(function (data) {
//Success here
})
.catch(({response}) => console.log(response.data)) //Here you get your errors
})
}