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>
);
}
}
Related
I have a react component that contains a div with a conditional visibility. The component represents the page of a specific product on an ecommerce. The users can give their opinions once. The div with the conditional visibility contains a textarea to write this opinion. But it should only be visible if the user hasn't written a review yet. This decision must be taken before loading the component. How do I do that?
This is the component:
import Axios from "axios";
import React, { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import NavbarHome from "./NavbarHome";
function Product() {
//Visivility of the form
let visibility = false;
useEffect(() => {
Axios.get("http://localhost:3001/review").then((response) => {
if (response.data.length === 0) {
visibility = true;
}
});
}, []);
const idprod = useParams();
//POST of the review
function handleSubmit(event) {
event.preventDefault();
let info = {
message: event.target.review.value,
rating: event.target.stars.value
};
if (!info.message || !info.rating) {
if (!info.message) {
alert("You haven't witten a review");
} else if (!info.rating) {
alert("You haven't give any stars");
}
} else {
Axios.post("http://localhost:3001/review", {
message: info.message,
rating: info.rating,
id_prod: idprod
}).then((response) => {
if (response.data.err) {
alert("You have already written a review for this product");
}
});
}
}
return (
<div>
<NavbarHome />
<div className="container-fluid" id="container-producto">
<div className="row">
<div className="col-sm-6 bloque-description-product">
<h2>Example</h2>
<p>Example</p>
<p>Example</p>
<p>Example</p>
</div>
</div>
<h4>Opinions</h4>
<div className="container-opinions">
{visibility ? (
<form onSubmit={handleSubmit}>
<p className="clasification">
<input id="radio1" type="radio" name="stars" value="5" />
<label htmlFor="radio1">★</label>
<input id="radio2" type="radio" name="stars" value="4" />
<label htmlFor="radio2">★</label>
<input id="radio3" type="radio" name="stars" value="3" />
<label htmlFor="radio3">★</label>
<input id="radio4" type="radio" name="stars" value="2" />
<label htmlFor="radio4">★</label>
<input id="radio5" type="radio" name="stars" value="1" />
<label htmlFor="radio5">★</label>
</p>
<textarea
name="review"
placeholder="Leave your review..."
></textarea>
<input type="submit"></input>
</form>
) : (
<div></div>
)}
</div>
</div>
</div>
);
}
export default Product;
The div with the conditional visibility is container-opinions.
I've already tried using onLoad on that container, but it is not working.
Any ideas?
You should change let variable with react state
import Axios from "axios";
import React, { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import NavbarHome from "./NavbarHome";
function Product() {
const [visibility, setVisibility] = useState(false)
useEffect(() => {
Axios.get("http://localhost:3001/review").then((response) => {
if (response.data.length === 0) {
setVisibility(true);
}
});
}, []);
const idprod = useParams();
//POST of the review
function handleSubmit(event) {
event.preventDefault();
let info = {
message: event.target.review.value,
rating: event.target.stars.value
};
if (!info.message || !info.rating) {
if (!info.message) {
alert("You haven't witten a review");
} else if (!info.rating) {
alert("You haven't give any stars");
}
} else {
Axios.post("http://localhost:3001/review", {
message: info.message,
rating: info.rating,
id_prod: idprod
}).then((response) => {
if (response.data.err) {
alert("You have already written a review for this product");
}
});
}
}
return (
<div>
<NavbarHome />
<div className="container-fluid" id="container-producto">
<div className="row">
<div className="col-sm-6 bloque-description-product">
<h2>Example</h2>
<p>Example</p>
<p>Example</p>
<p>Example</p>
</div>
</div>
<h4>Opinions</h4>
<div className="container-opinions">
{visibility ? (
<form onSubmit={handleSubmit}>
<p className="clasification">
<input id="radio1" type="radio" name="stars" value="5" />
<label htmlFor="radio1">★</label>
<input id="radio2" type="radio" name="stars" value="4" />
<label htmlFor="radio2">★</label>
<input id="radio3" type="radio" name="stars" value="3" />
<label htmlFor="radio3">★</label>
<input id="radio4" type="radio" name="stars" value="2" />
<label htmlFor="radio4">★</label>
<input id="radio5" type="radio" name="stars" value="1" />
<label htmlFor="radio5">★</label>
</p>
<textarea
name="review"
placeholder="Leave your review..."
></textarea>
<input type="submit"></input>
</form>
) : (
<div></div>
)}
</div>
</div>
</div>
);
}
export default Product;
You'll want to use the useState react hook to keep track of the visibility in a way your app can react to:
import Axios from "axios";
import React, { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import NavbarHome from "./NavbarHome";
function Product() {
//Visivility of the form
// THIS NEEDS TO BE useState
const [visibility, setVisibility] = useState(false)
useEffect(() => {
Axios.get("http://localhost:3001/review").then((response) => {
if (response.data.length === 0) {
// Use setVisibility to update the state
setVisibility(true);
}
});
}, []);
const idprod = useParams();
//POST of the review
function handleSubmit(event) {
event.preventDefault();
let info = {
message: event.target.review.value,
rating: event.target.stars.value
};
if (!info.message || !info.rating) {
if (!info.message) {
alert("You haven't witten a review");
} else if (!info.rating) {
alert("You haven't give any stars");
}
} else {
Axios.post("http://localhost:3001/review", {
message: info.message,
rating: info.rating,
id_prod: idprod
}).then((response) => {
if (response.data.err) {
alert("You have already written a review for this product");
}
});
}
}
return (
<div>
<NavbarHome />
<div className="container-fluid" id="container-producto">
<div className="row">
<div className="col-sm-6 bloque-description-product">
<h2>Example</h2>
<p>Example</p>
<p>Example</p>
<p>Example</p>
</div>
</div>
<h4>Opinions</h4>
<div className="container-opinions">
{visibility ? (
<form onSubmit={handleSubmit}>
<p className="clasification">
<input id="radio1" type="radio" name="stars" value="5" />
<label htmlFor="radio1">★</label>
<input id="radio2" type="radio" name="stars" value="4" />
<label htmlFor="radio2">★</label>
<input id="radio3" type="radio" name="stars" value="3" />
<label htmlFor="radio3">★</label>
<input id="radio4" type="radio" name="stars" value="2" />
<label htmlFor="radio4">★</label>
<input id="radio5" type="radio" name="stars" value="1" />
<label htmlFor="radio5">★</label>
</p>
<textarea
name="review"
placeholder="Leave your review..."
></textarea>
<input type="submit"></input>
</form>
) : (
<div></div>
)}
</div>
</div>
</div>
);
}
export default Product;
Goal:
If you select green in the radio. a input box text will appear below the radio input group. If you click another radio button, it will not displayed.
If you select blue in the radio. a input box text will appear below the radio input group. If you click another radio button, it will not displayed.
Problem:
I do not how to solve it. How would you solve it?
Info:
*Newbie in reactjs
Stackblitz:
https://stackblitz.com/edit/react-rpncls?
Thank you!
import React from 'react';
import './style.css';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
color: 'red'
};
this.onRadioChange = this.onRadioChange.bind(this);
}
onRadioChange = e => {
this.setState({
color: e.target.value
});
};
render() {
return (
<div className="App">
<form onSubmit={this.onSubmit}>
<strong>Select Color:</strong>
<ul>
<li>
<label>
<input
type="radio"
value="red"
checked={this.state.color === 'red'}
onChange={this.onRadioChange}
/>
<span>Red</span>
</label>
</li>
<li>
<label>
<input
type="radio"
value="green"
checked={this.state.color === 'green'}
onChange={this.onRadioChange}
/>
<span>Green</span>
</label>
</li>
<li>
<label>
<input
type="radio"
value="blue"
checked={this.state.color === 'blue'}
onChange={this.onRadioChange}
/>
<span>Blue</span>
</label>
</li>
<li>
<label>
<input
type="radio"
value="orange"
checked={this.state.color === 'orange'}
onChange={this.onRadioChange}
/>
<span>Ornage</span>
</label>
</li>
<li>
<label>
<input
type="radio"
value="purple"
checked={this.state.color === 'purple'}
onChange={this.onRadioChange}
/>
<span>Purple</span>
</label>
</li>
</ul>
<button type="submit">Choose Color</button>
</form>
</div>
);
}
}
You can conditionally render the text box depending on the color selected.
App.js:
import React from 'react';
import './style.css';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
color: 'red'
};
this.onRadioChange = this.onRadioChange.bind(this);
}
onRadioChange = e => {
this.setState({
color: e.target.value
});
};
textBoxVisible = () => {
return (this.state.color==="green" || this.state.color==="blue");
}
render() {
return (
<div className="App">
<form onSubmit={this.onSubmit}>
<strong>Select Color:</strong>
<ul>
<li>
<label>
<input
type="radio"
value="red"
checked={this.state.color === 'red'}
onChange={this.onRadioChange}
/>
<span>Red</span>
</label>
</li>
<li>
<label>
<input
type="radio"
value="green"
checked={this.state.color === 'green'}
onChange={this.onRadioChange}
/>
<span>Green</span>
</label>
</li>
<li>
<label>
<input
type="radio"
value="blue"
checked={this.state.color === 'blue'}
onChange={this.onRadioChange}
/>
<span>Blue</span>
</label>
</li>
<li>
<label>
<input
type="radio"
value="orange"
checked={this.state.color === 'orange'}
onChange={this.onRadioChange}
/>
<span>Ornage</span>
</label>
</li>
<li>
<label>
<input
type="radio"
value="purple"
checked={this.state.color === 'purple'}
onChange={this.onRadioChange}
/>
<span>Purple</span>
</label>
</li>
</ul>
{this.textBoxVisible() && <input type="text"/>}
<button type="submit" class="submitButton">Choose Color</button>
</form>
</div>
);
}
}
To make sure the text box and the submit button aren't on the same line, add this to style.css:
.submitButton{
display:block;
}
Maybe this can help.
const OPTIONS_DATA = [
{ id: "red", label: "Red", isEditable: false, isChecked: true },
{ id: "green", label: "Green", isEditable: false, isChecked: false },
{ id: "blue", label: "Blue", isEditable: false, isChecked: false },
{ id: "orange", label: "Orange", isEditable: false, isChecked: false }
];
export const App = () => {
const [options, setOptions] = React.useState(OPTIONS_DATA);
const handleChange = (evt) => {
const id = evt.target.value;
const formatOptions = options.map((opt) => {
if (opt.id === id) {
return {
...opt,
isChecked: true,
isEditable: true
};
}
return { ...opt, isChecked: false, isEditable: false };
});
setOptions(formatOptions);
};
return (
<div className="App">
<form>
<strong>Select Color:</strong>
<ul>
{options.map((item) => (
<li>
<label>
<input
type="radio"
value={item.id}
checked={item.isChecked}
onChange={handleChange}
/>
<span>{item.label}</span>
</label>
{item.isEditable && <input placeholder="Hello There" />}
</li>
))}
</ul>
<button type="submit">Choose Color</button>
</form>
</div>
);
};
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"
/>
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 trying to create a card element where users can vote "yes", "no", or "maybe" on an image. Right now it is reading like the radio buttons 90 options for one image, rather than 30 individual ones with 3 options. How do I map over each card so the form is specific to the image? The array will read as
{ userChoices: {
characterName[0]:choice.value,
characterName[1]:choice.value,
....
}}
const choiceCard = characterData.map((character, key) =>
<div className="col-sm-12 col-md-3" id="choiceCard" key={character.id}>
<div id="choiceContent">
<img src={character.statusImage}/>
<div id="choice-inner" className="form">
<span>{character.name}</span>
<div class="form-check">
<input
class="form-check-input"
type="radio"
name="yes"
id="yes"
value="yes"/>
<label class="form-check-label" for="yes">
Yes
</label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="radio"
name="no"
id="no"
value="no"/>
<label class="form-check-label" for="no">
No
</label>
</div>
<div class="form-check disabled">
<input class="form-check-input" type="radio" name="maybe" id="maybe" value="maybe"/>
<label class="form-check-label" for="maybe">
Maybe
</label>
</div>
</div>
</div>
</div>
);
You're close to where you want to be, there's just two things that need to be dealt with here:
Associating each set of buttons with a character.
Keeping track of the state for each character.
This is a natural use case for controlled components. A controlled radio button will look something like this:
<input
key={someID}
type="radio"
value={choice}
checked={this.state.choice === choice}
onChange={() => this.handleChange(choice)}
/>
with a change handler:
handleChange = newChoice => {
this.setState({
choice: choice
});
}
(see https://reactjs.org/docs/forms.html)
Applying this to your problem, you'd end up with something like this:
const choices = [
"Yes",
"No",
"Maybe"
]
const choiceCard = characterData.map((character, key) => {
return (
<label key={character.id}>
{character.name}
{choices.map(choice => {
return (
<input
key={choice}
type="radio"
value={choice}
checked={this.state.userChoices[key] === choice}
onChange={() => this.handleChange(choice, key)}
/>
);
})}
</label>
);
});
And the following change handler:
handleChange = (choice, key) => {
this.setState(prevState => ({
userChoices: { ...prevState.userChoices, [key]: choice }
}));
};
Here's a quick and dirty codepen you can play with to help your understanding: https://codepen.io/anon/pen/axzMxm?editors=0010