So I'm trying to enable a button, after two fields have been selected, but for some reason, I have to click on the second field twice to trigger it to enabled. Can anyone see what I'm doing wrong?
So to confirm, when I click on a price and when I click on donateTo field, it is setting state correctly, however it doesn't enable the bottom at the bottom until I have clicked one of the fields a third or fourth time.
const DonateBox = ({ goToPayment }) => {
const [price, setPrice] = useState('');
const [donateTo, setDonateTo] = useState('');
const [isProgressDisabled, setDisabled] = useState(true);
const handleSetDonateTo = (e) => {
setDonateTo(e.target.value);
disabledCheck();
};
const handlePriceClick = (e) => {
setPrice(e.target.value);
disabledCheck();
};
const handleGoToPayment = () => {
goToPayment('paymentbox');
};
const disabledCheck = () => {
if (price && donateTo) {
setDisabled(false);
}
console.log(isProgressDisabled);
};
return (
<>
<div className={styles.donateBox}>
<p className={styles.heading}>
Give through the most effective platform for good.
</p>
<p className={styles.subheading}>
100% goes to the causes listed in the article here. You are one click
away!
</p>
<div className={styles.itemList}>
<label className={styles.labelWrapper}>
<input
type="radio"
className={styles.customRadio}
value="cause"
onClick={handleSetDonateTo}
checked={donateTo === 'cause'}
/>
<span>Donate to Cause</span>
</label>
<label className={styles.labelWrapper}>
<input
type="radio"
className={styles.customRadio}
value="charity"
onClick={handleSetDonateTo}
checked={donateTo === 'charity'}
/>
<span>Donate to Charity</span>
</label>
<label className={styles.labelWrapper}>
<input
type="radio"
className={styles.customRadio}
value="goods"
onClick={handleSetDonateTo}
checked={donateTo === 'goods'}
/>
<span>Donate to Goods</span>
</label>
</div>
<div className={styles.priceList}>
<label
className={`${styles.priceLabel} ${
price === '25' ? `${styles.selected}` : ''
}`}
>
<input
type="radio"
name="25"
className={styles.priceInput}
onClick={handlePriceClick}
value="25"
/>
$25
</label>
<label
className={`${styles.priceLabel} ${
price === '50' ? `${styles.selected}` : ''
}`}
>
<input
type="radio"
name="50"
className={styles.priceInput}
onClick={handlePriceClick}
value="50"
/>
$50
</label>
<label
className={`${styles.priceLabel} ${
price === '75' ? `${styles.selected}` : ''
}`}
>
<input
type="radio"
name="75"
className={styles.priceInput}
onClick={handlePriceClick}
value="75"
/>
$75
</label>
</div>
</div>
<button
className={styles.largeButton}
onClick={handleGoToPayment}
disabled={isProgressDisabled}
>
Add Card Details
</button>
</>
);
};
export default DonateBox;
In addition to #adesurirey's suggestion, this is the perfect scenario for useEffect.
When the variable(s) inside of the dependency array are changed, the code in useEffect is invoked.
Meaning, you can automatically invoke the disabledCheck if price or donateTo are changed. This way you don't have to remember to call disabledCheck within the handlers.
Edit another excellent thing about useEffect in a scenario like this is that you know for sure disabledCheck is invoked only after state is changed. Since mutating state is async, it is possible that disabledCheck was running before state was actually updated.
Think of useEffect like the callback function within setState (on class based components)..
// Class based comparison...
// You know for sure `disabledCheck` is only called *after*
// state has been updated
setState({
some: 'newState'
}, () => disabledCheck());
Demo:
const { useState, useEffect, Fragment } = React;
const { render } = ReactDOM;
const DonateBox = ({ goToPayment }) => {
const [price, setPrice] = useState('');
const [donateTo, setDonateTo] = useState('');
const [isProgressDisabled, setDisabled] = useState(true);
const handleSetDonateTo = (e) => {
setDonateTo(e.target.value);
// disabledCheck();
};
const handlePriceClick = (e) => {
setPrice(e.target.value);
// disabledCheck();
};
const handleGoToPayment = () => {
goToPayment('paymentbox');
};
const disabledCheck = () => {
if (price !== '' && donateTo !== '') {
setDisabled(false);
}
console.log(isProgressDisabled);
};
useEffect(() => {
disabledCheck();
}, [price, donateTo]);
return (
<Fragment>
<div>
<p>
Give through the most effective platform for good.
</p>
<p>
100% goes to the causes listed in the article here. You are one click
away!
</p>
<div>
<label>
<input
type="radio"
value="cause"
onClick={handleSetDonateTo}
checked={donateTo === 'cause'}
/>
<span>Donate to Cause</span>
</label>
<label>
<input
type="radio"
value="charity"
onClick={handleSetDonateTo}
checked={donateTo === 'charity'}
/>
<span>Donate to Charity</span>
</label>
<label>
<input
type="radio"
value="goods"
onClick={handleSetDonateTo}
checked={donateTo === 'goods'}
/>
<span>Donate to Goods</span>
</label>
</div>
<div>
<label>
<input
type="radio"
name="25"
onClick={handlePriceClick}
value="25"
/>
$25
</label>
<label>
<input
type="radio"
name="50"
onClick={handlePriceClick}
value="50"
/>
$50
</label>
<label>
<input
type="radio"
name="75"
onClick={handlePriceClick}
value="75"
/>
$75
</label>
</div>
</div>
<button
onClick={handleGoToPayment}
disabled={isProgressDisabled}
>
Add Card Details
</button>
</Fragment>
);
};
const App = () => <DonateBox />
render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
You should use onChange events on your inputs instead of onClick
<input
type="radio"
name="75"
className={styles.priceInput}
onChange={handlePriceClick}
value="75"
/>
Related
I've been trying to make a form where, depending on a switch button, renders one or two different inputs.
My code looks like this:
const Test = () => {
const [switchButton, setSwitch] = React.useState(true)
const handleSwitch = () => {setstate(!switchButton)}
return <>
<Switch checked={switchButton} onClick={() => handleSwitch} />
{!switchButton ?
<>
<label htmlFor="input_1">Input 1</label>
<input id="input_1"/>
</>
:
<>
<label htmlFor="input_2">Input 2</label>
<input id="input_2" />
<label htmlFor="input_3">Input 3</label>
<input id="input_3" />
</>
}
</>
}
export default Test;
My issue happens when I enter characters into one input and then switch them: The same characters are shown on my new rendered input. Example here.
Why does this happen? I'm really lost
use keys for the elements, so it will not be recognized as the same element as react tries to map elements on each rerender if they were already rendered before.
so react sees: 1 input and than 2 inputs and thinks the first input is the same as before.
const Test = () => {
const [switchButton, setSwitch] = React.useState(true)
const handleSwitch = () => setSwitch((switch) => !switch)
return (
<>
<Switch checked={switch} onClick={handleSwitch} />
{!switchButton ? (
<React.Fragment key="key1">
<label htmlFor="input_1">Input 1</label>
<input id="input_1"/>
</>
) : (
<React.Fragment key="key2">
<label htmlFor="input_2">Input 2</label>
<input id="input_2" />
<label htmlFor="input_3">Input 3</label>
<input id="input_3" />
</>
)}
</>
)}
export default Test;
but anyway it would be better to use a controlled input. something like this:
const [value, setValue] = React.useState(true)
<input value={value} onChange={(e) => setValue(e.target.value)}/>
I have a radio input buttons in JSX like below.
import React, { Component, useState, useEffect, useRef } from 'react';
import { Link, Redirect } from 'react-router-dom';
import { useDispatch, connect } from 'react-redux';
import { updateReviewAction } from '../actions/dashboard';
const EditReviewComponent = (props) => {
const [role, setRole] = useState(null);
const [message, setMessage] = useState('');
const [isMessage, setIsMessage] = useState(false);
const [jobKnowledge, setJobKnowledge] = useState('');
const [productivity, setProductivity] = useState('');
const [workQuality, setWorkQuality] = useState('');
const [skills, setSkills] = useState('');
const dispatch = useDispatch();
const onUpdateReview = (event) => {
event.preventDefault();
let reviewID = props.viewReviews.response._id;
dispatch(updateReviewAction({ reviewID, jobKnowledge, productivity, workQuality, skills }));
setMessage('');
setIsMessage(true);
}
console.log(props.viewReviews);
const onRoleChange = event => {
setRole(event.target.value);
}
const onJobKnowledgeChange = event => {
setJobKnowledge(event.target.value);
}
const onProductivityChange = event => {
setProductivity(event.target.value);
}
const onWorkQualityChange = event => {
setWorkQuality(event.target.value);
}
const onSkillsChange = event => {
setSkills(event.target.value);
}
const resetMessage = () => {
setIsMessage(false);
}
return (
<div className='employees'>
<Link to={`${props.url}`}>Close</Link>
<h3>Edit New Employee</h3>
<p>{(message !== '' && isMessage) ? message : ''}</p>
<form onSubmit={onUpdateReview}>
<div>
<p>Job Knowledge</p>
<label htmlFor="excellent_knowledge">
<input
type="radio"
name="job_knowledge"
id="excellent_knowledge"
value="Excellent"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.jobKnowledge === 'Excellent')
? true
: false
}
onChange={onJobKnowledgeChange}
required
/>
Excellent
</label>
<label htmlFor="good_knowledge">
<input
type="radio"
name="job_knowledge"
id="good_knowledge"
value="Good"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.jobKnowledge === 'Good')
? true
: false
}
onChange={onJobKnowledgeChange}
required
/>
Good
</label>
<label htmlFor="fair_knowledge">
<input
type="radio"
name="job_knowledge"
id="fair_knowledge"
value="Fair"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.jobKnowledge === 'Fair')
? true
: false
}
onChange={onJobKnowledgeChange}
required
/>
Fair
</label>
<label htmlFor="poor_knowledge">
<input
type="radio"
name="job_knowledge"
id="poor_knowledge"
value="Poor"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.jobKnowledge === 'Poor')
? true
: false
}
onChange={onJobKnowledgeChange}
required
/>
Poor
</label>
</div>
<div>
<p>Productivity</p>
<label htmlFor="excellent_productivity">
<input
type="radio"
name="productivity"
id="excellent_productivity"
value="Excellent"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.productivity === 'Excellent')
? true
: false
}
onChange={onProductivityChange}
required
/>
Excellent
</label>
<label htmlFor="good_productivity">
<input
type="radio"
name="productivity"
id="good_productivity"
value="Good"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.productivity === 'Good')
? true
: false
}
onChange={onProductivityChange}
required
/>
Good
</label>
<label htmlFor="fair_productivity">
<input
type="radio"
name="productivity"
id="fair_productivity"
value="Fair"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.productivity === 'Fair')
? true
: false
}
onChange={onProductivityChange}
required
/>
Fair
</label>
<label htmlFor="poor_productivity">
<input
type="radio"
name="productivity"
id="poor_productivity"
value="Poor"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.productivity === 'Poor')
? true
: false
}
onChange={onProductivityChange}
required
/>
Poor
</label>
</div>
<div>
<p>Work Quality</p>
<label htmlFor="excellent_quality">
<input
type="radio"
name="quality"
id="excellent_quality"
value="Excellent"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.workQuality === 'Excellent')
? true
: false
}
onChange={onWorkQualityChange}
required
/>
Excellent
</label>
<label htmlFor="good_quality">
<input
type="radio"
name="quality"
id="good_quality"
value="Good"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.workQuality === 'Good')
? true
: false
}
onChange={onWorkQualityChange}
required
/>
Good
</label>
<label htmlFor="fair_quality">
<input
type="radio"
name="quality"
id="fair_quality"
value="Fair"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.workQuality === 'Fair')
? true
: false
}
onChange={onWorkQualityChange}
required
/>
Fair
</label>
<label htmlFor="poor_quality">
<input
type="radio"
name="quality"
id="poor_quality"
value="Poor"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.workQuality === 'Poor')
? true
: false
}
onChange={onWorkQualityChange}
required
/>
Poor
</label>
</div>
<div>
<p>Technical Skills</p>
<label htmlFor="excellent_skills">
<input
type="radio"
name="skills"
id="excellent_skills"
value="Excellent"
checked={
(
props.viewReviews.hasOwnProperty('response') &&
props.viewReviews.response.skills === 'Excellent'
)
}
onChange={onSkillsChange}
required
/>
Excellent
</label>
<label htmlFor="good_skills">
<input
type="radio"
name="skills"
id="good_skills"
value="Good"
checked={
(
props.viewReviews.hasOwnProperty('response') &&
props.viewReviews.response.skills === 'Good'
)
}
onChange={onSkillsChange}
required
/>
Good
</label>
<label htmlFor="fair_skills">
<input
type="radio"
name="skills"
id="fair_skills"
value="Fair"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.skills === 'Fair')
}
onChange={onSkillsChange}
required
/>
Fair
</label>
<label htmlFor="poor_skills">
<input
type="radio"
name="skills"
id="poor_skills"
value="Poor"
checked={
(props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.skills === 'Poor')
}
onChange={onSkillsChange}
required
/>
Poor
</label>
</div>
<div>
<button>Update</button>
</div>
</form>
</div>
);
}
const mapStateToProps = state => (state);
export default connect(mapStateToProps)(EditReviewComponent);
as you can see I am checking them on a condition. With this condition they are properly checked. However, when I try to click on another radio button then it does not get checked anymore. The radio buttons are frozen.
What am I doing wrong and how can I fix it.
UPDATE
I updated the whole component. Please let me know what to do.
The checked attribute indicates the default value to be selected from the list of radio buttons. In your code you are trying to set checked from the props passed into the component, but this is not what you are updating when click one of the radio buttons.
When clicking a radio button, you are updating the state with these:
const [jobKnowledge, setJobKnowledge] = useState('');
const [productivity, setProductivity] = useState('');
const [workQuality, setWorkQuality] = useState('');
So, instead of determining the value of checked from props, try determining it using these state variables and I think it will work for you.
<input
type="radio"
name="job_knowledge"
id="excellent_knowledge"
value="Excellent"
checked={jobKnowledge === "Excellent"}
onChange={onJobKnowledgeChange}
required
/>
PS: Based on the way you were checking the value of this variable:
props.viewReviews.hasOwnProperty('response') && props.viewReviews.response.jobKnowledge === 'Excellent'
You might want to check out optional chaining
I am new to react. I have almost 15 input controls on UI. Some are dropdowns, some are textboxes, couple of calender controls and radio buttons. I want to retrive all values before submitting a page. Do I need to define 15 props in state object of component for 15 inputs? is there any way to have it in one object.
Also how to set the values of each control. For example for textbox I know, its like
<input type="text" name="username" className="form-control" id="exampleInput" value={this.props.name} onChange={this.handleChange} placeholder="Enter name"></input>
How to handle same for dropdown,calender and radio buttton. Thanks in advance.
Normally, these wouldn't be props, they'd be state (which is different). You can use objects in state. If you're doing a class-based component (class YourComponent extends React.Component), state is always an object you create in the constructor and update with setState. If you're doing this in a function component, typically you use separate state variables for each thing (const [name, setName] = useState("");), but you can use an object if you prefer. There's more about state in the documentation.
That said, if you only want the values when you take an action, you could make the inputs "uncontrolled."
Here's a three-input example using a class component:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
firstName: "",
lastName: "",
about: ""
};
this.handleChange = this.handleChange.bind(this);
}
handleChange({target: {name, value}}) {
this.setState({[name]: value});
}
render() {
const {firstName, lastName, about} = this.state;
const {handleChange} = this;
return <div>
<div>
<label>
First name:
<br/>
<input type="text" value={firstName} name="firstName" onChange={handleChange} />
</label>
</div>
<div>
<label>
Last name:
<br/>
<input type="text" value={lastName} name="lastName" onChange={handleChange} />
</label>
</div>
<div>
<label>
About you:
<br />
<textarea value={about} name="about" onChange={handleChange} />
</label>
</div>
<div>{firstName} {lastName} {(firstName || lastName) && about ? "-" : ""} {about}</div>
</div>;
}
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Here's one using a functional component with discrete state items (usually best):
const { useState } = React;
const Example = () => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [about, setAbout] = useState("");
// There's are lots of ways to do this part, this is just one of them
const handleChange = ({target: {name, value}}) => {
switch (name) {
case "firstName":
setFirstName(value);
break;
case "lastName":
setLastName(value);
break;
case "about":
setAbout(value);
break;
}
};
return <div>
<div>
<label>
First name:
<br/>
<input type="text" value={firstName} name="firstName" onChange={handleChange} />
</label>
</div>
<div>
<label>
Last name:
<br/>
<input type="text" value={lastName} name="lastName" onChange={handleChange} />
</label>
</div>
<div>
<label>
About you:
<br />
<textarea value={about} name="about" onChange={handleChange} />
</label>
</div>
<div>{firstName} {lastName} {(firstName || lastName) && about ? "-" : ""} {about}</div>
</div>;
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Here's one using a functional component with an object in state:
const { useState } = React;
const Example = () => {
const [data, setData] = useState({firstName: "", lastName: "", about: ""});
const handleChange = ({target: {name, value}}) => {
setData(current => ({...current, [name]: value}));
};
const {firstName, lastName, about} = data;
return <div>
<div>
<label>
First name:
<br/>
<input type="text" value={firstName} name="firstName" onChange={handleChange} />
</label>
</div>
<div>
<label>
Last name:
<br/>
<input type="text" value={lastName} name="lastName" onChange={handleChange} />
</label>
</div>
<div>
<label>
About you:
<br />
<textarea value={about} name="about" onChange={handleChange} />
</label>
</div>
<div>{firstName} {lastName} {(firstName || lastName) && about ? "-" : ""} {about}</div>
</div>;
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Here is the sample code, I used in my application.
class CreditCardForm extends React.Component {
constructor() {
super()
this.state = {
name: '',
address: '',
ccNumber: ''
}
}
handleChange(e) {
// If you are using babel, you can use ES 6 dictionary syntax
// let change = { [e.target.name] = e.target.value }
let change = {}
change[e.target.name] = e.target.value
this.setState(change)
}
render() {
return (
<form>
<h2>Enter your credit card details</h2>
<label>
Full Name
<input type="name" onChange={(e)=>this.handleChange(e)} value={this.state.name} />
</label>
<label>
Home address
<input type="address" onChange={(e)=>this.handleChange(e)} value={this.state.address} />
</label>
<label>
Credit card number
<input type="ccNumber" onChange={(e)=>this.handleChange(e)} maxlength="16" value={this.state.ccNumber} />
</label>
<button type="submit">Pay now</button>
</form>
)
}
}
You can set name for input and update state base on event.target.name and event.target.value
constructor() {
super();
this.state = {
text: "",
select: "",
radio: ""
};
}
handeInput = e => {
this.setState({
[e.target.name]: e.target.value
});
};
render() {
console.log(this.state);
return (
<div className="App">
<input
onChange={this.handeInput}
type="input"
name="text"
value={this.state.text}
/>
<select
name="select"
onChange={this.handeInput}
value={this.state.select}
>
<option value="option1">option1</option>
<option value="option2">option2</option>
</select>
<input
type="radio"
name="radio"
value="Option1"
checked={this.state.radio === "Option1"}
onChange={this.handeInput}
/>
Option1
<input
type="radio"
name="radio"
value="Option2"
checked={this.state.radio === "Option2"}
onChange={this.handeInput}
/>
Option2
</div>
);
}
You can check here CodeSandBox Hope it helps
I am trying to set up some functionality on this React component so that a user can add and remove empty radio button options to a page that a user can type text into. The only issue that I am having is that I am relatively new to React and am not 100% how to do this.
import React, { Component } from 'react';
class TextRadio extends Component {
constructor() {
super();
state = {
textValue: ""
}
};
handleInputChange = event => {
const value = event.target.value;
const name = event.target.name;
this.setState({
[name]: value
});
}
addBox = () => {
}
removeBox = () => {
}
render() {
return(
<div>
<div className="form-check">
<input className="form-check-input" type="radio" id="" name="" value="" />
<label className="form-check-label" for="">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button type="button" className="btn btn-danger" onClick={this.removeBox}>
Remove Option
</button>
</div>
);
}
}
export default TextRadio;
The result that I am expecting to happen is to have it so the component can add and remove radio button options from the page depending on the button that the user presses
i was completed just your addBox and RemoveBox functions, i hope that's help you
import React, { Component } from "react";
class TextRadio extends Component {
constructor() {
super();
this.state = {
radioButtons: []
};
}
handleInputChange = event => {
const value = event.target.value;
const name = event.target.name;
};
addBox = () => {
this.setState(prevstate => {
let radioButtons = prevstate.radioButtons;
if (radioButtons.length === 0) {
radioButtons.push({
id: 1,
name: "radiobutton",
value: "test"
});
return {
radioButtons: radioButtons
};
} else {
radioButtons.push({
id: radioButtons[radioButtons.length - 1].id + 1,
name: "raiodButton_" + (radioButtons[radioButtons.length - 1].id + 1),
value: radioButtons[radioButtons.length - 1].value
});
return {
radioButtons: radioButtons
};
}
});
};
removeBox = () => {
this.setState(prevstate => {
let radioButtons = prevstate.radioButtons;
if (radioButtons.length !== 0) {
radioButtons.pop(radioButtons[radioButtons.length - 1]);
return {
radioButtons: radioButtons
};
} else {
return { radioButtons: radioButtons };
}
});
};
render() {
return (
<div>
<div className="form-check">
{this.state.radioButtons.map(radiobutton => {
return (
<div>
<input
className="form-check-input"
type="radio"
id={radiobutton.id}
name={radiobutton.name}
value={radiobutton.value}
/>
<label className="form-check-label" for="">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
);
})}
</div>
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button
type="button"
className="btn btn-danger"
onClick={this.removeBox}
>
Remove Option
</button>
</div>
);
}
}
export default TextRadio;
https://codesandbox.io/embed/confident-browser-tmojp
I was playing around with your idea and made some changes in the code, just to show you an example, how you can dynamically create new components and store them in applications state and then render out to user based on their actions.
I created new component just for form UI: option, input field and remove button. If user clicks on the Add Option, new item of the component is added to application state and then render out. Remove button is used to remove Item from state.
class TextRadio extends Component {
state = {
optionInputs: []
};
addBox = () => {
const optionInputsUpdated = [
...this.state.optionInputs,
<OptionInput id={uuid.v4()} remove={this.removeBox} />
];
this.setState({ optionInputs: optionInputsUpdated });
};
removeBox = id => {
const optionInputsUpdated = this.state.optionInputs.filter(
item => item.props.id !== id
);
this.setState({ optionInputs: optionInputsUpdated });
};
render() {
return (
<div>
{this.state.optionInputs.map((optionInput, idx) => {
return (
<div key={idx} test="123">
{optionInput}
</div>
);
})}
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
</div>
);
}
}
const OptionInput = props => {
return (
<div className="form-check">
<input
className="form-check-input"
type="radio"
id=""
name="radio"
value=""
/>
<label className="form-check-label" for="">
<input className="form-control" type="text" placeholder="" />
</label>{" "}
<button
type="button"
className="btn btn-danger"
onClick={() => props.remove(props.id)}
>
Remove Option
</button>
</div>
);
};
Hope this gives you better understanding, how to achieve your goal.
If you need additional help, just post a comment under this answer, and I will update demo to help you.
Here is DEMO I created from your code: https://codesandbox.io/s/nice-ganguly-s4wls
first you have to initialize an empty array state
this.state={
radioButtons : [{input:''}]
}
then in your return statement you have to loop through the radioButtons array and show the radio button with input
{
this.state.radioButtons.map(item => (
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
))
}
then in your addBox function append an object on every click
addBox = () => {
this.setState({radioButtons:[...this.state.radioButtons, {input:''}]})
}
function to remove a radio button object
removeBox = () => {
let radioArray = this.state.radioButtons
radioArray.pop()
this.setState({radioButtons:radioArray})
}
Final code Looks like this :
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component{
constructor(props){
super(props);
this.state={
radioButtons :[{input:''}]
}
}
addBox = () => {
this.setState({radioButtons:[...this.state.radioButtons, {input:''}]})
}
removeBox = () => {
let radioArray = this.state.radioButtons
radioArray.pop()
this.setState({radioButtons:radioArray})
}
render(){
return(
<div>
{
this.state.radioButtons.map(item => (
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
))
}
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button type="button" className="btn btn-danger" onClick={this.removeBox}>
Remove Option
</button>
</div>
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
codepen Example
I am not able to click or select on any of my radio buttons. Can someone help me out how to work with radio buttons in react?
I tried removing e.preventDefault() but that didn't help either.
Here's what my code looks like:
File 1:
this.state = {
fields: {
gender: ''
}
}
fieldChange(field, value) {
this.setState(update(this.state, { fields: { [field]: { $set: value } } }));
}
<Form
fields={this.state.fields}
onChange={this.fieldChange.bind(this)}
onValid={() => handleSubmit(this.state.fields)}
onInvalid={() => console.log('Error!')}
/>
File 2:
render() {
const { fields, onChange, onValid, onInvalid, $field, $validation } = this.props;
return (
{/* Gender */}
<div id={styles.genderField} className={`form-group ${styles.formGroup} ${styles.projName}`}>
<label className="col-sm-2 control-label">Gender:</label>
<div className="col-sm-10">
<label className="radio-inline">
<input type="radio" name="gender" id="male"
checked={fields.gender === "Male"}
value={fields.gender} {...$field( "gender", e => onChange("gender", e.target.value)) } />
Male
</label>
<label className="radio-inline">
<input type="radio" name="gender" id="female"
checked={fields.gender === "Female"}
value={fields.gender} {...$field( "gender", e => onChange("gender", e.target.value)) } />
Female
</label>
</div>
</div>
<div className={`modal-footer ${styles.modalFooter}`}>
<button
className={`btn btn-primary text-white ${styles.saveBtn}`}
onClick={e => {
e.preventDefault();
this.props.$submit(onValid, onInvalid);
}}
>
Save
</button>
</div>
)
}
That's not how the docs handle onChange events. https://reactjs.org/docs/handling-events.html
You need to provide the full code to be able to help with that particular component.
Check out this working example: https://stackblitz.com/edit/react-radiobtns
class App extends Component {
constructor(props) {
super(props);
this.state = {selectedOption: 'option1'};
// This binding is necessary to make `this` work in the callback
this.handleOptionChange = this.handleOptionChange.bind(this);
}
handleOptionChange(changeEvent) {
this.setState({
selectedOption: changeEvent.target.value
});
}
render() {
return (
<form>
<label>
<input
onChange={this.handleOptionChange}
type="radio" value="option1"
checked={this.state.selectedOption === 'option1'}
name="radio1"/>
Option 1
</label>
<label>
<input
onChange={this.handleOptionChange}
checked={this.state.selectedOption === 'option2'}
type="radio"
value="option2"
name="radio1"/>
Option 2
</label>
<label>
<input
onChange={this.handleOptionChange}
checked={this.state.selectedOption === 'option3'}
type="radio"
value="option3"
name="radio1"/>
Option 3
</label>
</form>
);
}
}