How to manage state with complex json object in react js - reactjs

Below is the code I have so far, my state isn't working as expected with a bit complex object, I was able to work with a simple object with no nested objects in my state and its working as expected.
state assignment works fine if I don't use personalInfo or contactInfo inside the customer object and used all the properties and create simple customer object
import React, {PropTypes} from 'react';
import {Grid,Row,Col,Button,Label} from 'react-bootstrap';
import {connect} from 'react-redux';
import * as customerActions from '../../actions/customerActions';
import {bindActionCreators} from 'redux';
class AddCustomer extends React.Component{
constructor(props , context){
super(props , context);
this.state={
customer:{
personalInfo:{
firstName:"",
lastName:"",
dob:"",
ssn:""
},
contactInfo:{
address:"",
addressLine2:"",
city:"",
state:"",
zip:"",
phoneNumber:"",
emailAddress:""
}
}
};
this.handleChange = this.handleChange.bind(this);
this.onClickCancel = this.onClickCancel.bind(this);
this.onClickSave = this.onClickSave.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
customer: {
personalInfo:{
},
contactInfo:{
},
...this.state.customer,
[name]: value
}
});
console.log(this.state.customer);
}
onClickCancel(){
}
onClickSave(){
this.props.actions.createCustomer(this.state.customer);
}
render() {
return (
<div className="container-fluid">
<Grid>
<Row className="show-grid">
<Col xs={10} md={10}><b>ADD A LEAD</b></Col>
<Col xs={2} md={2}>
<Button>×</Button>
</Col>
</Row>
<Row className="show-grid">
<Col xs={12} md={12}>
<hr/>
</Col>
</Row>
<p><b>Personal Information</b></p>
<br/>
<Row className="show-grid">
<Col xs={6} md={6}>
<Row><Label>First Name*</Label></Row>
<Row><input name="personalInfo.firstName" type="text" value={this.state.customer.personalInfo.firstName} onChange={this.handleChange} required="true"/></Row>
</Col>
<Col xs={6} md={6}>
<Row><Label>Last Name*</Label></Row>
<Row><input name="personalInfo.lastName" type="text" value={this.state.customer.personalInfo.lastName} onChange={this.handleChange} required="true"/></Row>
</Col>
</Row>
<br/>
<Row className="show-grid">
<Col xs={2} md={2}>
<Row><Label>Date of Birth*</Label></Row>
<Row><input name="personalInfo.dob" type="text" value={this.state.customer.personalInfo.dob} onChange={this.handleChange} required="true"/></Row>
</Col>
<Col xs={2} md={2}>
<Row><Label>SSN*</Label></Row>
<Row><input name="personalInfo.ssn" type="text" value={this.state.customer.personalInfo.ssn} onChange={this.handleChange} required="true"/></Row>
</Col>
</Row>
<br/>
<p><b>Contact Information</b></p>
<br/>
<Row className="show-grid">
<Col xs={6} md={6}>
<Row><Label>Address</Label></Row>
<Row><input name="contactInfo.address" type="text" value={this.state.customer.contactInfo.address} onChange={this.handleChange}/></Row>
</Col>
<Col xs={6} md={6}>
<Row><Label>Address Line 2</Label></Row>
<Row><input name="contactInfo.addressLine2" type="text" value={this.state.customer.contactInfo.addressLine2} onChange={this.handleChange}/></Row>
</Col>
</Row>
<br/>
<Row className="show-grid">
<Col xs={2} md={2}>
<Row><Label>City</Label></Row>
<Row><input name="contactInfo.city" type="text" value={this.state.customer.contactInfo.city} onChange={this.handleChange}/></Row>
</Col>
<Col xs={2} md={2}>
<Row><Label>State</Label></Row>
<Row><input name="contactInfo.state" type="text" value={this.state.customer.contactInfo.state} onChange={this.handleChange}/></Row>
</Col>
<Col xs={2} md={2}>
<Row><Label>Zip</Label></Row>
<Row><input name="contactInfo.zip" type="text" value={this.state.customer.contactInfo.zip} onChange={this.handleChange}/></Row>
</Col>
</Row>
<br/>
<Row className="show-grid">
<Col xs={4} md={4}>
<Row><Label>Phone Number</Label></Row>
<Row><input name="contactInfo.phoneNumber" type="text" value={this.state.customer.contactInfo.phoneNumber} onChange={this.handleChange}/></Row>
</Col>
<Col xs={4} md={4}>
<Row><Label>Email Address</Label></Row>
<Row><input name="contactInfo.emailAddress" type="text" value={this.state.customer.contactInfo.emailAddress} onChange={this.handleChange}/></Row>
</Col>
</Row>
<br/>
<Row className="show-grid">
<hr/>
</Row>
<Row className="show-grid">
<input className="pull-right" type="submit" onClick={this.onClickCancel} value="Cancel"/>
<input className="pull-right" type="submit" bsStyle="primary" onClick={this.onClickSave} value="Add"/>
</Row>
</Grid>
</div>
);
}
}
AddCustomer.propTypes={
actions:PropTypes.object.isRequired,
customer:PropTypes.array.isRequired
};
function mapStateToProps(state, ownProps) {
return{
customer:state.customer
};
}
function mapDispatchToProps(dispatch) {
return{
actions: bindActionCreators(customerActions,dispatch)
};
}
export default connect(mapStateToProps,mapDispatchToProps)(AddCustomer);

I'm not sure what's the unxepcted result do you receive, but I gues you may try something like this:
handleChange(type, name, event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
this.setState({
customer: {
...this.state.customer,
[type]:{
...this.state.customer[type],
[name]: value
}
}
});
console.log(this.state.customer);
}
...
render() {
...
<Row><input type="text" value={this.state.customer.personalInfo.firstName} onChange={this.handleChange.bind(this, 'personalInfo', 'firstName')} required="true"/></Row>
...
<Row><input type="text" value={this.state.customer.contactInfo.address} onChange={this.handleChange.bind(this, 'contactInfo', 'address')}/></Row>
...
}

Related

Increment or decrement a value in react array while mapping

export default class Cart extends Component {
constructor(props) {
super(props);
this.state = {
selectedForCart: [],
checkOut: true,
priceQuantity: undefined,
total: undefined,
};
}
render() {
return (
<div>
<NavBar />
{this.state.selectedForCart &&
this.state.selectedForCart.map((v, i) => {
return (
<Container className="mt-5" key={i}>
<Row>
<Col lg={2} md={2} sm={12}>
<p>
Price: ₹
{v.priceTaxIncluded}
</p>
<p style={{ fontSize: "10px" }}>Tax inclusive</p>
</Col>
<Col lg={2} md={2} sm={12}>
<Form.Group>
<Form.Label>Quantity</Form.Label>
<Form.Control
type="number"
placeholder="Quantity"
value={1}
onChange={(e) => {
this.setState({
priceQuantity: e.target.value
});
console.log(v.priceTaxIncluded * e.target.value);
}}
/>
</Form.Group>
</Col>
<Col lg={2} md={2} sm={12}>
{this.state.checkOut && (
<>
<p>{this.state.priceQuantity}</p>
</>
)}
</Col>
</Row>
</Container>
);
})}
<Footer />
</div>
);
}
}
Here in the above code, I'm mapping an array of items from the state object "" value. And if I increment a specific item, then that specific item's quantity only should increment. But it is not happening all items are getting incremented. And also the price should be multiplied with the incremented value and should be shown...
Thank You.
As in this image, I'm changing the quantity. But If I change the quantity of a product, then its reflecting the price for all products. As I have only one state object
You can bind the priceQuantity to input value. Then conditionally render in last column. As you are trying to print priceQuantity in last column it will show for all rows.
this.state = {
...
priceQuantity: 0,
..
};
{this.state.selectedForCart &&
this.state.selectedForCart.map((v, i) => {
return (
<Container className="mt-5" key={i}>
<Row>
<Col lg={2} md={2} sm={12}>
<p>
Price: ₹
{v.priceTaxIncluded}
</p>
<p style={{ fontSize: "10px" }}>Tax inclusive</p>
</Col>
<Col lg={2} md={2} sm={12}>
<Form.Group>
<Form.Label>Quantity</Form.Label>
<Form.Control
type="number"
placeholder="Quantity"
value={this.state.priceQuantity}
onChange={(e) => {
this.setState({
priceQuantity: e.target.value
});
console.log(v.priceTaxIncluded * e.target.value);
}}
/>
</Form.Group>
</Col>
<Col lg={2} md={2} sm={12}>
{this.state.checkOut && (
<>
<p>{this.state.priceQuantity ? v.priceTaxIncluded * this.state.priceQuantity : 0}</p>
</>
)}
</Col>
</Row>
</Container>
);
})}

How to edit a data file from another Page in ReactJS

I have 2 pages: (1) First page is simply a Data file [Data.js]. (2) I have a Page with a form where after i fill it up and i press save it store all the data from the form in a set like {name:"name",price:"price"} and i want somehow to send this set to the Data file that is full of sets like:
const dataCommunity = [
{
id:"1",
titolo:"Community - Quote for API",
costo:"99€",
descrizione:"sono creato dinamicamente",
attività:"Prodotto",assets:"Competence"
},
{
id:"2",
titolo:"Community - Quote for API",
costo:"9999999€",
descrizione:"sono creato dinamicamente",
attività:"Prodotto",
assets:"Competence"
},
{
id:"3",
titolo:"Community Titolo Diverso - Quote for API",
costo:"999999999999€",
descrizione:"sono creato dinamicamente",
attività:"Prodotto",
assets:"Competence"
}
]
export default dataCommunity;
Now the other file may be confusing but i know for sure that const data that is inside the handlerSubmit() gives me back a set {data inside} correctly because i tested with console.log so the only thing is how do i update the data file from this page using the data i collected?
class AttivaCommunity extends React.Component{
constructor(props){
super(props)
this.state={
titolo:"",
costo:"",
attività:"",
assets:"",
descrizione:"",
search:""
}
}
updateSearch(event){
this.setState({search:event.target.value.substr(0,20)})
}
handleSubmit=(event)=>{
event.preventDefault()
const data = this.state
console.log(data)
}
render(){
let offers = dataCommunity.filter(
(offer)=>{return offer.titolo.indexOf(this.state.search) !== -1}
);
return(
<div>
<MPheader/>
<Link to="/Marketing/Marketing/Nuovo prodotto"><button className="myButton" type="button" style={{margin:"10px"}}>Aggiungi</button></Link>
<IslandersHeader nome="HUI MARKETPLACE" sottoheader="Buy all Hui apps and services and sell your Island’s goods and services"/>
<Container fluid className="MainPageRow2">
<Form onSubmit={this.handleSubmit}>
<Form.Row className="Col_margin py-5 px-1">
<Col md={2} className="Col_margin px-1">
<TextForm nome="Nome"/>
</Col>
<Col md={2} className="Col_margin px-1">
<SelectDa4 nome="Island" option1="Tutte" option2="Approvato" option3="In attesa" option4="Rifiutato"/>
</Col>
<Col md={2} className="Col_margin px-1">
<SelectDa4 nome="Attività" option1="Prodotto" option2="Mercato" option3="Foundraising" option4="Corporate"/>
</Col>
<Col md={2} className="Col_margin px-1">
<SelectDa4 nome="Asset" option1="Prodotto" option2="Mercato" option3="Foundraising" option4="Corporate"/>
</Col>
<Col md={2} className="Col_margin px-1">
<SelectDa3 nome="Risultati per Pagina" option1="10" option2="20" option3="30"/>
</Col>
<Col md={2} className="Col_margin px-1">
<Form.Label className="checktext">Cerca</Form.Label>
<Form.Control type="text" placeholder={this.props.nome} value={this.state.search} onChange={this.updateSearch.bind(this)} name="cerca"/>
</Col>
</Form.Row>
<Form.Row className="Col_margin px-1 py-2">
<button className="myButton" type="submit" style={{marginLeft:"30px"}}>Filtra</button>
</Form.Row>
</Form>
</Container>
<Container fluid className="MainPageRow2">
<Row className="Col_margin py-1 px-1">
{offers.map((offerta)=> <MarketDiv key={offerta.id} titolo={offerta.titolo} costo={offerta.costo} descrizione={offerta.descrizione} attività={offerta.attività} assets={offerta.assets}/>)}
</Row>
</Container>
</div>
)
}
}
export default AttivaCommunity

React Send form data to email

I am using create-react-app or my project. I created a form field where I store the data into the state. I would like to send the data as an email, and I'm lost on how to do so.
One of the problems is using create-react-app, I'm not sure where to find my router or server page in node.
Any help would be greatly appreciated.
import React, { Component } from 'react';
import { Button, Col, Grid, Row, Form, FormGroup, FormControl,
ControlLabel, Checkbox } from 'react-bootstrap';
export class Contact extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
email: "",
message: ""
}
}
onChange = (e) => {
const state = this.state;
state[e.target.name] = e.target.value;
this.setState(state);
}
onSubmit = (e) => {
e.preventDefault();
const { name, email, message } = this.state;
}
render() {
const { name, email, message } = this.state;
return(
<div>
<Grid>
<Row id="contactForm">
<Col xs={2}>
</Col>
<Col xs={8}>
<Form horizontal onSubmit={this.onSubmit}>
<FormGroup >
<Col componentClass={ControlLabel} sm={2}>
Name
</Col>
<Col sm={10}>
<FormControl required value={name} name="name" type="name"
placeholder="Name" onChange={this.onChange} />
</Col>
</FormGroup>
<FormGroup controlId="formHorizontalPassword">
<Col componentClass={ControlLabel} sm={2}>
Email
</Col>
<Col sm={10}>
<FormControl required value={email} name="email" type="email"
placeholder="Email" onChange={this.onChange}/>
</Col>
</FormGroup>
<FormGroup>
<Col componentClass={ControlLabel} bsSize="lg" sm={2}>
Message
</Col>
<Col sm={10}>
<FormControl required value={message} name="message" componentClass="textarea" style={{ height: 200 }}
type="message" placeholder="Insert message here" onChange={this.onChange}/>
</Col>
</FormGroup>
<FormGroup>
<Col smOffset={2} sm={10}>
<Checkbox>Flag as important</Checkbox>
</Col>
</FormGroup>
<FormGroup>
<Col smOffset={2} sm={10}>
<Button type="submit">
Send
</Button>
</Col>
</FormGroup>
</Form>
</Col>
<Col xs={2}>
</Col>
</Row>
</Grid>
</div>
)
}
}
Short answer is that You cannot send mail from the client. You will need to have a server to do so. If you have an api service that your React is consuming from, then it is very possible from there.

How to make a form secure in redux-form

I am trying to use redux-form to build a credit card info form. However, when the user put in their card details on it, this pop up appear:
it said
Automatic credit card filling is disabled because this form does not use a secure connection
So my question is how to make a form secure using redux-form?
This is the code where I input the Payment redux-form
import React from 'react'
import { connect } from 'react-redux'
import PaymentView from './Payment.js'
import { reduxForm } from 'redux-form'
class Payment extends React.Component{
render() {
const { cardDetail } = this.props
return(<PaymentView onCheckOut={()=>console.log(cardDetail)} />)
}
}
Payment = reduxForm({
form: 'payment'
})(Payment)
const mapStateToProps = state => ({
cardDetail : state.form.payment ? state.form.payment.values : null
})
export default connect(mapStateToProps)(Payment)
This is the code for my Payment View
import React from 'react'
import { Panel, Button, Row, Col } from 'react-bootstrap'
import { TextInput } from '.Form'
export default ({onCheckOut})=> <div>
<Row>
<Col sm={12} md={8} lg={6} mdOffset={2} lgOffset={3}>
<Panel className="scb" header="bank transfer">
123-456-789
</Panel>
</Col>
</Row>
<Row>
<Col sm={12} md={8} mdOffset={2} lg={6} lgOffset={3}>
<Panel className="credit-card" header="credit card" >
<Row>
<Col sm={12} md={8} lg={6}>
<TextInput
name="creditCard"
label="credit card number"
type="text"
validateState="success"
controlId="credit-card"
value="12345678910111213"
placeholder="xxxx xxxx xxxx xxxx"
onChange={()=>{}}
helptext="16card number"
>
card number
</TextInput>
</Col>
</Row>
<Row>
<Col sm={12} md={8} lg={6}>
<TextInput
name="name"
label="name"
type="text"
validateState="success"
controlId="name-card"
value="steve jobs"
placeholder="steve jobs"
onChange={()=>{}}
helptext="name on card"
>
Name on Card
</TextInput>
</Col>
</Row>
<Row>
<Col sm={8} md={8} lg={8}>
<h5>Expiry Date</h5>
</Col>
</Row>
<Row>
<Col sm={4} md={2} lg={2}>
<TextInput
name="month"
label="month"
type="text"
validateState="success"
controlId="month"
value="12"
placeholder="01"
onChange={()=>{}}
helptext="month"
>
month
</TextInput>
</Col>
<Col sm={4} md={2} lg={2}>
<TextInput
name="year"
label="year"
type="text"
validateState="success"
controlId="year"
value="18"
placeholder="18"
onChange={()=>{}}
helptext="year"
>
Year
</TextInput>
</Col>
</Row>
<Row>
<Col sm={12} md={4} lg={4}>
<TextInput
name="cvv"
label="cvv"
type="text"
validateState="cvv"
controlId="cvv"
value="123"
placeholder="123"
onChange={()=>{}}
helptext="cvv"
>
Cvv
</TextInput>
</Col>
</Row>
<Row>
<Col sm={12} md={4} lg={4}>
<Button bsStyle="primary" bsSize="large" block onClick={onCheckOut}>
Pay Now
</Button>
</Col>
</Row>
</Panel>
</Col>
</Row>
</div>
This is my TextInput
export const TextInput = (
{
type,
name,
placeholder,
helpTextArray,
status,
label,
value
}
) =>
<FormGroup
name="formBasicText"
validationState={status || null}
>
<ControlLabel>{label}</ControlLabel>
<Field
className="form-control"
id="formBasicText"
name={name}
component="input"
type={type}
placeholder={placeholder}
/>
<FormControl.Feedback />
{
value !== null?
helpTextArray.map( (helpText, key) =>
<HelpBlock key={key}>{helpText}</HelpBlock>
): null
}
</FormGroup>
This is most likely happening because the web page where that form is found is not served over HTTPS. Chrome automatically disables credit card information autofilling in those cases to stop your credit card information from falling into malicious hands through for example
Network traffic snooping (your credit card details being transmitted over a public Wi-Fi or other network in plaintext)
Man-in-the-Middle injection (somebody intercepting the non-encrypted HTTP traffic and injecting malicious code that captures credit card details)
Even if your page is served over HTTPS already, this issue might pop up if your page has content like images or external scripts that are served over a regular HTTP connection.
You have this message maybe because you don't use a 'HTTPS' connexion and your navigator detect that and disabled auto-filling ?

How to pass information from a form into a function in react

I have a login model with the following login function:
login() {
console.log("Hello. It's Me")
axios.post('https://crossorigin.me/http://requestb.in/w21igbw2', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
//this.setState({ showModal: false });
})
.catch(function (error) {
console.log(error);
});
}
this is working fine, so how I do change this to send the actual data from the login form instead of just the hardcoded info in the function. The input in the login model this is what the full form looks like:
<form>
<FormGroup >
<Row>
<Col md={12}>
<input className="col-md-10 col-md-offset-1 top-space fat-input" placeholder="Email"/>
<input className="col-md-10 col-md-offset-1 top-space fat-input" placeholder="Password"/>
</Col>
</Row>
<Row className='top-space'>
<Col md={5} mdOffset={1}>
<Checkbox className="checkbox-login"> Remember Me </Checkbox>
</Col>
<Col md={6} className='forgot-password'>
Forgot Password
</Col>
</Row>
<Row className='top-space'>
<Col md={10} mdOffset={1}>
<Button onClick={this.login} bsStyle="btn btn-black btn-block">Login</Button>
</Col>
</Row>
</FormGroup>
</form>
You can keep track of inputs in you state and when you fire API read the values from the state.
constructor(){
super()
this.state = {
email : null,
password : null,
}
onChangeEmail(){
this.setState({email: e.target.value});
}
onChangePassword(){
this.setState({password: e.target.value});
}
login(){
//api call with state values for id and pass
}
render(){
<form>
<FormGroup >
<Row>
<Col md={12}>
<input className="col-md-10 col-md-offset-1 top-space fat-input" placeholder="Email" onChange={this.onChangeEmail}/>
<input className="col-md-10 col-md-offset-1 top-space fat-input" placeholder="Password" onChange={this.onChangePassword}/>
</Col>
</Row>
<Row className='top-space'>
<Col md={5} mdOffset={1}>
<Checkbox className="checkbox-login"> Remember Me </Checkbox>
</Col>
<Col md={6} className='forgot-password'>
Forgot Password
</Col>
</Row>
<Row className='top-space'>
<Col md={10} mdOffset={1}>
<Button onClick={this.login} bsStyle="btn btn-black btn-block">Login</Button>
</Col>
</Row>
</FormGroup>
</form>
}
}
P.S: I would strongly suggest using redux with react and using redux-form to handle you forms. It has been the best way I have found till now to handle forms in react-redux app. You can check it out here.

Resources