how to set state for input element created dynamically - reactjs

I'm creating an input element using document.createElement and setting the attribute. i would like to have an onchange event which will update the state.
how can i proceed? following is my code
addoffers = () => {
var input = document.createElement("input");
input.setAttribute('name', 'whatweoffer'.concat(Math.floor((Math.random() * 1000) + 1)));
input.setAttribute('class','form-control mb-3');
input.setAttribute('placeholder','what we offer');
input.onchange = this.handleChange;
var parent = document.getElementById("offerinput");
parent.appendChild(input);
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
console.log(e.target.value);
}
<input type="text" className="form-control mb-3" id='whatweoffer' name='whatweoffer' onChange={this.handleChange} placeholder='what we offer' required />

Try this
class DynamicInputs {
constructor(props) {
super(props);
this.state = {
inputs : []
}
}
render() {
return (
<React.Fragment>
{
this.state.inputs.map(inputValue =>{
<input key= {inputValue} type="text" placeholder="what we offer" className="form-control mb-3" name = {`whatweoffer${inputValue}`} onChange = {this.handleChange} required/> })
}
</React.Fragment>
)
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
console.log(e.target.value);
}
addInput() = () =>{
let {inputs} = this.state;
inputs.push((Math.floor((Math.random() * 1000) + 1))
this.setState({
inputs
})
}
}

Although there's accepted answer but I want to give you another approach.
Instead of create input dynamically, why don't you just use own component's state to decide if an input is displayed or not, and other attributes are just state values. For example:
render() {
const {
isInputDisplayed, inputName, inputId, inputClasses, inputPlaceholder,
} = this.state;
return (
{ isInputDisplayed && (
<input type="text" name={inputName} id={inputId} className={inputClasses} placeholder={inputPlaceholder} />
)}
);
}

Related

react - this = undefined, how to pass the prop into my function

I have passed my user ID into my 'OrderMessages' component but in my function says undefined. When my user submits a messages using the form in the handleFormSubmit function I need the UserID and the datetime of the message. I have managed to get the date and time but when trying to console log to get the UserID I keep getting an error. I have tried this.props.... and this.state but both say undefined, can you please help. In my constructor I have tested using const UserId = props.location.state.UserID; and in debug I can see this has correctly got the UserID so im not sure how to get it into my hadleFormSubmit function.
import React from "react";
import Moment from "moment";
import { Form, Button } from "react-bootstrap";
class OrderMessages extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: false,
checkboxes: [],
selectedId: [],
formLableSelected: "",
formSelectedSubject: "",
formSelectedSubjectId: "",
formNewSubject: "",
formChainID: "",
formMessageBody: "",
userId: '',
};
const UserId = props.location.state.UserID;
}
componentDidMount() {
this.setState({ isLoading: true });
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url =
"myURL" +
this.props.location.state.orderNumber;
fetch(proxyurl + url)
.then((res) => res.json())
.then((data) => this.setState({ data: data, isLoading: false }));
}
handleClick = (id) => {
if (this.state.selectedId !== id) {
this.setState({ selectedId: id });
} else {
this.setState({ selectedId: null });
}
};
setformSubjectID(messageSubject) {
if (messageSubject.subject === this.state.formSelectedSubject) {
this.setState({ formSelectedSubjectId: messageSubject.messageSubjectId });
}
}
handleChangeSubject = (event) => {
this.setState({ formSelectedSubject: event.target.value });
this.state.data.message_Subjects.map((ms) => this.setformSubjectID(ms));
};
handleFormSubmit(e) {
e.preventDefault();
// get current time
let submit_time = Moment().format("ddd DD MMM YYYY HH:mm:ss");
console.log("messageDatetime", submit_time);
// get user id THIS IS WHAT DOESN’T WORK
console.log("messageSentFrom", this.state.userId);
console.log("messageSentFrom", this.props.location.state.UserID);
}
render() {
const { data, isLoading } = this.state;
if (isLoading) {
return <p>Loading ...</p>;
}
if (data.length === 0) {
return <p> no data found</p>;
}
console.log("mess: ", data);
return (
<div>
<div className="sendMessageContent">
<Form className="sendMessageForm" onSubmit={this.handleFormSubmit}>
<Form.Group className="formRadio">
<Form.Check
className="formRadiob"
type="radio"
label="New chat"
value="new"
name="neworexisitng"
id="New Message"
onChange={this.onFormMessageChanged}
defaultChecked
/>
<Form.Check
className="formRadiob"
type="radio"
label="Reply to exisiting chat"
value="reply"
name="neworexisitng"
id="exisiting Message"
onChange={this.onFormMessageChanged}
/>
</Form.Group>
{this.returnCorrectFormFields(data)}
<Form.Group>
<Form.Label>Message Body</Form.Label>
<Form.Control as="textarea" rows={3} />
</Form.Group>
<Button variant="primary" type="submit">
Send Message
</Button>
</Form>
</div>
</div>
);
}
returnCorrectFormFields(data) {
if (this.state.formLableSelected === "new") {
return this.newMessageSubject(data);
} else {
return this.choseMessageSubject(data);
}
}
choseMessageSubject(data) {
return (
<Form.Group>
<Form.Label>Select the message subject</Form.Label>
<Form.Control as="select" onChange={this.handleChangeSubject}>
<option value="0">Choose...</option>
{data.message_Subjects.map((ms) => (
<option value={ms.subject}>{ms.subject}</option>
))}
</Form.Control>
</Form.Group>
);
}
newMessageSubject(data) {
return (
<Form.Group>
<Form.Label>Enter Message Subject</Form.Label>
<Form.Control type="text" placeholder="Enter message subject" />
</Form.Group>
);
}
onFormMessageChanged = (event) => {
this.setState({
formLableSelected: event.target.value,
});
};
getAllMessageInChain(messageChain) {
return (
<div className="messageHistory">
<div className="messageHistoryHeader">
<div className="innerMS-history-body">Message</div>
<div className="innerMS">Date and Time</div>
<div className="innerMS">Message sent by</div>
</div>
{messageChain.map((ms) => (
<div className="messageHistoryBody">
<div className="innerMS-history-body">{ms.messageBody}</div>
<div className="innerMS">
{Moment(ms.dateTime).format("ddd DD MMM YYYY hh:mm:ss")}
</div>
<div className="innerMS">{ms.sentFromId}</div>
</div>
))}
</div>
);
}
getLatestMessageDateTime(messageChain) {
const lastmessage = messageChain.length - 1;
Moment.locale("en");
var dt = messageChain[lastmessage].dateTime;
return Moment(dt).format("ddd DD MMM YYYY hh:mm:ss");
}
}
export default OrderMessages;
The scope of this isn't the component in the function you're using.
Either change handleFormSubmit to this to bind this automatically.
handleFormSubmit = (e) => {
// .. your code
}
or bind this manually in the constructor
constructor() {
// ..other code
this.handleFormSubmit = this.handleFormSubmit.bind(this)
}

Why is React state not changing simultaneously with input change for a controlled component

I don't think I missed anything in making the form a controlled component. Why doesn't the state doesn't change as characters are being input?
class AddChores extends Component {
state = {
chore: "",
};
handleChange = (evt) => {
this.setState({ chore: evt.target.value });
};
handleSubmit = (evt) => {
evt.preventDefault();
this.props.addChores(this.state);
this.setState({ chore: "" });
};
render() {
console.log(this.state);
return (
<div>
<form onClick={this.handleSubmit}>
<input
type="text"
placeholder="New Chore"
value={this.state.chore}
onChange={this.handleChange}
/>
<button className="button">ADD CHORE</button>
</form>
</div>
);
}
}[![React dev tool showing no simultaneous update][1]][1]
I made some changes as below and it works fine for me. Hope it helps you too.
class AddChores extends Component {
constructor(props) {
super(props);
this.state = {
chore: ""
};
}
handleChange = (event) => {
this.setState({
chore: event.target.value
});
};
handleSubmit = (evt) => {
evt.preventDefault();
// this.props.addChores(this.state);
this.setState({ chore: "" });
};
componentDidUpdate(){
console.log('the state', this.state.chore)
}
render() {
return (
<div>
<form onClick={this.handleSubmit}>
<input
type="text"
placeholder="New Chore"
value={this.state.chore}
onChange={this.handleChange}
/>
</form>
</div>
);
}
}
not sure why is this happening but try using the second form of setState
this.setState(() => ({ chore: evt.target.value}))
check this https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

React Form: Input Data Won't Display

Every time I click the button a post is being created and displayed
But the input data isn't showing up
import React, { Component } from 'react'
export default class App extends Component {
state = {
dataArr : [],
isClicked: false,
title : '',
img : ''
}
handleSubmit = (e) => {
e.preventDefault()
}
handleChange = (e) => {
[e.target.name] = e.target.value
}
handleClick = () => {
const copyDataArr = Object.assign([], this.state.dataArr)
copyDataArr.push({
title : this.state.title,
img : this.state.img
})
this.setState({
isClicked : true,
dataArr : copyDataArr
})
}
render() {
console.log(this.state.title)
return (
<div>
<form onSubmit={this.handleSubmit}>
<input type="text" name="title" placeholder="Title.." onChange={this.handleChange}/>
<input type="text" name="img" placeholder="Image.." onChange={this.handleChange}/>
<button onClick={this.handleClick}>SUBMIT</button>
</form>
{ this.state.isClicked ?
this.state.dataArr.map(
(post, index) => {
return(
<div class="div">
<h1>title: {post.title}</h1>
<img src={post.img} alt="ohno"/>
</div>
)
}
)
: null }
</div>
)
}
}
Created an empty array on state and copied the array and pushed in the input values. What am I doing wrong?
Need the onChange to work and the input data to display
Trying to learn forms in react. Hope someone can help out
Your handleChange function is not updating state with the data you enter to the inputs. Looks like you might have forgotten to call this.setState(). Try this
:
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
Also here is a sandbox with the working code: https://codesandbox.io/s/distracted-darkness-xp3nu
You have to add a value attribute to the input tag and pass the state value.
<input type="text" name="title" value={this.state.title} placeholder="Title.." onChange={this.handleChange}/>
Your handle change function should be as follows
handleChange = (e) => {
this.setState({[e.target.name] : e.target.value});
}

How to fix inifnity loop?

Hi guys i have this problem. I have input and dropdown I need choose from option dropdown and write value on input but first value was everytime empty. I solved this problem with componentDidUpdate and set locationValue on undefined. After i have sometimes this error.How can I fixed it? I need change lifecycle method or what ?
Here is code
class AccordionForm extends Component {
state = {
value: '',
locationValue: undefined,
};
componentDidUpdate() {
const { nameOptions } = this.props;
if (nameOptions && nameOptions && this.state.locationValue === undefined) {
this.setState({
locationValue: nameOptions[0],
});
}
}
handleChangeInputSelect = ({ target }) => {
this.setState({
locationValue: target.value,
});
};
handleChangeInput = ({ target }) =>
this.setState({
value: target.value,
});
onSubmit = event => {
const { value, locationValue } = this.state;
const { handleSubmitForm } = this.props;
event.preventDefault();
handleSubmitForm(value, locationValue);
this.setState({ value: '' });
};
render() {
const { name, nameOptions } = this.props;
const { value } = this.state;
return (
<Form className="accordion_form" name={name} onSubmit={this.onSubmit}>
<FormGroup className="form-group-locations">
{nameOptions && (
<Input
className="form-input"
required
name={name}
type="select"
onChange={this.handleChangeInputSelect}
>
{nameOptions.map((option, index) => {
return (
<option key={index} value={option}>
{option}
</option>
);
})}
</Input>
)}
<Input
placeholder={`add new ${name}...`}
type="text"
required
name={name}
value={value}
onChange={this.handleChangeInput}
className="form-input"
/>
<Button className="tagBtn" color="success" type="submit">
Add
</Button>
</FormGroup>
</Form>
);
}
}
export default AccordionForm;
This could be happening because at the first instance your nameOptions[0] is undefined. Please update your if statement's conditions like this:
componentDidUpdate() {
const { nameOptions } = this.props;
if (nameOptions && !!nameOptions.length && nameOptions[0] && this.state.locationValue !== nameOptions[0]) {
this.setState({
locationValue: nameOptions[0],
});
}
}

Hot to get value of button in react

I have a form with steps name, email, util.
When a have input I can get the value inserts, but when a have input button with options true or false, I can't get the values.
This is my code:
class CreateData extends Component {
state = {
step: 1,
nome:'',
email:'',
util: '',
}
nextStep = () => {
const { step } = this.state
this.setState({
step : step + 1
})
}
prevStep = () => {
const { step } = this.state
this.setState({
step : step - 1
})
}
handleChange = input => event => {
this.setState({
[input] : event.target.value,
})
}
renderSwitch(step) {
const { nome, email, util } = this.state;
const values = { nome, email, util};
switch (step) {
case 1:
return <UserName
nextStep = {this.nextStep}
handleChange = {this.handleChange}
values = {values}
/>
case 2:
return <UserEmail
nextStep = {this.nextStep}
prevStep = {this.prevStep}
handleChange = {this.handleChange}
values = {values}
/>
case 3:
return <UserUtil
nextStep = {this.nextStep}
prevStep = {this.prevStep}
handleChange = {this.handleChange}
values = {values}
/>
case 4:
return <CrossHomePage/>
}
}
render() {
const {step} = this.state;
return (
<div>
<HeaderPage />
{this.renderSwitch(step)}
</div>
);
}
}
export default CreateData
In my component to get name is ok:
class UserName extends Component{
saveAndContinue = (e) => {
e.preventDefault()
this.props.nextStep()
}
render(){
const { values } = this.props;
return(
<Grid className={style.container}>
<Form>
<fieldset>
<input
className="input"
onChange={this.props.handleChange('nome')}
defaultValue={values.nome}
type="text"
required
/>
</fieldset>
<Button className="button" onClick={this.saveAndContinue}> Continue </Button>
</Form>
</Grid>
)
}
}
export default UserName;
But in my component to get button value doesn't work, I want to get the value of the button clicked.
<input
type="button"
className="input"
onChange={values.moradia[1]}
value='yes'
defaultValue={values.util}
onClick={ this.saveAndContinue }
/>
<input
type="button"
className="input"
onChange={values.util}
value='no'
defaultValue={values.util}
onClick={ this.saveAndContinue }
/>
How I do get the value of the button clicked in this case and save this value to invoke in another component?
Example here.
I want to get value of buttons yes or no
https://codesandbox.io/s/r1lm9j22l4
Using event.target.value
Add value property to Button
<Button className="button" value="continue" onClick={this.saveAndContinue}> Continue </Button>
saveAndContinue = (e) => {
e.preventDefault();
console.log(e.target.value); //will give you the value continue
this.props.nextStep();
}

Resources