Correct way of using useState hook on radio buttons - reactjs

I followed the ReactJS documentation regarding the useState hook but I cannot get it to work with radio buttons. It doesn't select any radio button at all.
By the way I am using react-semantic ui for the component.
The radio buttons should select the gender assigned to the state. I've tried to console.log the gender variable and it changes but does not reflect on the ui.
Here's my code for your reference.
import React, { useState } from 'react';
const ListCreateNew = () => {
const [gender, setGender] = useState('Male');
return (
<Form.Group inline>
<label>Gender</label>
<Form.Field control={Radio} label="Male" checked={gender === 'Male'} value="Male" onClick={() => setGender('Male')} />
<Form.Field control={Radio} label="Female" checked={gender === 'Female'} value="Female" onClick={() => setGender('Female')} />
</Form.Group>
);
}
EDIT:
I apologize everyone. I've missed the anonymous function on the onClick attrib.

You should use annonymous function to update the state,
<Form.Field control={Radio} label="Male" checked={gender === 'Male'} value="Male" onClick={() => setGender('Male')} />
<Form.Field control={Radio} label="Female" checked={gender === 'Female'} value="Female" onClick={() => setGender('Female')} />
Update
For the radio button, you have Form.Radio
<Form.Group inline>
<label>Gender</label>
<Form.Radio label="Male" checked={gender === 'Male'} value="Male" onClick={() => setGender('Male')} />
<Form.Radio label="Female" checked={gender === 'Female'} value="Female" onClick={() => setGender('Female')} />
</Form.Group>

const [radio,setRadio] = useState('false')
<Form>
<Form.Check inline label="Response A" type="radio" id="radioA" value="radioA" checked={radio === "radioA"} onChange={(e)=>{setRadio(e.target.value)}}/>
<Form.Check inline label="Response B" type="radio" id="radioB" value="radioB" checked={radio === "radioB"} onChange={(e)=>{setRadio(e.target.value)}}/>
<Form.Check inline label="Response C" type="radio" id="radioC" value="radioC" checked={radio === "radioC"} onChange={(e)=>{setRadio(e.target.value)}}/>
<Form.Check inline label="Response D" type="radio" id="radioD" value="radioD" checked={radio === "radioD"} onChange={(e)=>{setRadio(e.target.value)}}/>
</Form>

Related

Validating radio button with React Hook Form

I have a custom radio button component in React looking like this:
export default function SingleSelectionButton(props) {
const {
values, name, required, errors, defaultData,
xs, md, register, infoBox, infoBoxContent, validateField } = props;
return (
<>
<Form.Group>
<Form.Label>
<FormattedMessage
id={name}
/>
</Form.Label>
{values.map((value) => (
<span key={value} className="SingleSelectionButton">
<input
{...register(name, { required: required}
id={name + value}
type="radio"
name={name}
value={value}
defaultChecked={defaultData.primary[name] === value}
/>
<label htmlFor={name + value}>
<FormattedMessage id={value} />
</label>
</span>
))}
</Form.Group>
</>
);
};
I call it like this, using an array for the different values:
<SingleSelectionButton
name="us_person"
md={6}
values={["yes", "no"]}
register={register}
required={true}
errors={errors}
validateField="no"
/>
The validation with required is working fine.
The problem is that I don't manage to validate a value in particular.
I have tried the following:
<input
{...register(name, { required: required, validate: value => value === validateField })}
id={name + value}
type="radio"
name={name}
value={value}
defaultChecked={defaultData.primary[name] === value}
/>
And also:
<input
{...register(name, { required: required, pattern: validateField })}
id={name + value}
type="radio"
name={name}
value={value}
defaultChecked={defaultData.primary[name] === value}
/>
So far no joy. What am I missing?

React js show/hide specific element using Material UI checkbox's state

hello I'm trying to show and hide specific elements with checkbox material and what is happening now is when one checkbox is checked all the hidden divs are showing up.
You can see the problem here: https://stackblitz.com/edit/react-1ecdqb?file=demo.tsx
edit: I know that I need more variables in the state but I ask if there is a way to do it without state for each checkbox because there are gonna be 10 more checkboxes
const UninstallView = () => {
const [isChecked, setIsChecked] = useState(false);
const handleChange = event => {
if (event.target.checked) {
setIsChecked(true);
}
else {
setIsChecked(false);
}
}
return (
<div>
<FormGroup>
<FormControlLabel control={<Checkbox onChange={handleChange} />} label="simple isn't what I expected" />
{isChecked ? <TextField
id="filled-multiline-static"
label="What did you expect from simple?"
multiline
rows={4}
defaultValue=""
variant="filled"
/>
: '' }
</FormGroup>
<FormGroup>
<FormControlLabel control={<Checkbox onChange={handleChange} />} label="simple isn't working correctly" />
{isChecked ?
<div>
<h1>hello</h1>
</div>
: '' }
</FormGroup>
</div>
);
You are sharing 1 state across 2 checkboxes. You should have a separate state that holds the state for each checkbox.
This code may help:
const UninstallView = () => {
const [isFirstChecked, setIsFirstChecked] = useState(false);
const [isSecondChecked, setIsSecondChecked] = useState(false);
return (<div>
<FormGroup>
<FormControlLabel
control={<Checkbox onChange={() => setIsFirstChecked(!isFirstChecked)}/>}
label="simple isn't what I expected"/>
{isFirstChecked ? <TextField
id="filled-multiline-static"
label="What did you expect from simple?"
multiline
rows={4}
defaultValue=""
variant="filled"
/> : ''}
</FormGroup>
<FormGroup>
<FormControlLabel
control={<Checkbox onChange={() => setIsSecondChecked(!isSecondChecked)}/>}
label="simple isn't working correctly"/>
{isSecondChecked ? <div>
<h1>hello</h1>
</div> : ''}
</FormGroup>
</div>);
}
Sandbox example

adding color to the active radio button

I have two radio buttons and I want to add a background color to the active radio button.
I tried to add it via a condition but it seems to be not working. What am i doing wrong here?
I'm getting Cannot read property 'gender' of undefined error
import React from "react";
import "./App.css";
export default function App() {
const [gender, setGender] = React.useState();
return (
<div className="App">
<Radio
label="male"
value="male"
checked={gender}
setter={setGender}
style={{backgroundColor: this.state.gender == 'male' ? 'red': 'white'}}
/>
<Radio
label="female"
value="female"
checked={gender}
setter={setGender}
style={{backgroundColor: this.state.gender == 'female' ? 'red': 'white'}}
/>
</div>
);
}
const Radio = ({ label, value, checked, setter }) => {
return (
<div className="radio">
<label>
<input
type="radio"
checked={checked === value}
onChange={() => setter(value)}
/>
<span>{label}</span>
</label>
</div>
);
When using react hooks, you do not need to use this.state.gender...
Try this:
<div className="App">
<Radio
label="male"
value="male"
checked={gender}
setter={setGender}
style={{backgroundColor: gender === 'male' ? 'red': 'white'}}
/>
<Radio
label="female"
value="female"
checked={gender}
setter={setGender}
style={{backgroundColor: gender === 'female' ? 'red': 'white'}}
/>
</div>
Few changes required
1-Always provide initial value
const [gender, setGender] = React.useState('');
2- Since you are using hooks, don't need to use this.state
style={{backgroundColor: gender === 'male' ? 'red': 'white'}}
If you are trying to change background color on selection of radio button, Replace Radio component with below.
const Radio = ({ label, value, checked, setter, style }) => {
return (
<div className="radio" style={style}>
<label>
<input
type="radio"
checked={checked === value}
onChange={() => setter(value)}
/>
<span>{label}</span>
</label>
</div>
);
};
Live demo

Material UI radio button issue

I'm using material-ui.com components in reactjs (wrapped with next.js).
When page hot-reload it works.
But when I reload the page (ctr+r).
here is the code I used FormControl, RadioGroup, FormControlLabel and Radio to create a radio button, but it is not working.
I don't know what's wrong please help.
<div className="form-group-custom col-sm-4">
<FormControl component="fieldset">
<RadioGroup
row
aria-label="position"
name="position"
defaultValue="top"
>
<FormControlLabel
value={"open"}
control={
<Radio
color="primary"
name="time"
checked={
campaignDetail.time === "open"
? true
: false
}
onChange={(event) =>
handleInputChange(event)
}
/>
}
label={
<>
Always Open (
<i className="fas fa-crown"></i>{" "}
Premium)
</>
}
/>
<FormControlLabel
value={"time"}
name="time"
control={
<Radio
color="primary"
checked={
campaignDetail.time === "time"
? true
: false
}
onChange={(event) =>
handleInputChange(event)
}
/>
}
label="Time Bound"
/>
</RadioGroup>
</FormControl>
</div>

Clear values in number input in React

I have two radio buttons, under each there are two number inputs. The goal is to clear the values that belong to deselected radio immediately on selecting the other radio.
I tried to resolve it by adding the ternary operator to defaultValue:
defaultValue={props.xxx ? props.yyy.toString() : ''}
But this works only when I refresh the page after selecting the radio, which isn't what I need. What is the way to clear the fields immediately when I select the other radio? I have read all similar questions here, but nothing helped in my situation.
The code is like this:
<Input
type="radio"
id="radio1"
label=""
name="radio"
onChange={() => onSomeChange(AbC, true)}
defaultChecked={props.aaa === true}
/>
<div className={cx({hidden: props.ooo})}>
{props.xxx === AbC && (
<div>
<Input
type="number"
id="min-number"
name="min-max1"
label=""
defaultValue={props.xxx ? props.yyy.toString() : ''}
onBlur={(e) => onOtherChange(true, inputValue(e.target.value))}
/>
<Input
type="number"
id="max-number"
name="min-max1"
label=""
defaultValue={props.xxx ? props.yyy.toString() : ''}
onBlur={(e) => onOtherChange(false, inputValue(e.target.value))}
/>
</div>
)}
<Input
type="radio"
id="radio2"
label=""
name="radio"
onChange={() => onSomeChange(AbC, true)}
defaultChecked={props.aaa === true}
/>
<div className={cx({hidden: !props.ooo})}>
{props.xxx === AbC && (
<div>
<Input
type="number"
id="min-number2"
name="min-max2"
label=""
defaultValue={props.xxx ? props.yyy.toString() : ''}
onBlur={(e) => onOtherChange(true, inputValue(e.target.value))}
/>
<Input
type="number"
id="min-number2"
name="min-max2"
label=""
defaultValue={props.xxx ? props.yyy.toString() : ''}
onBlur={(e) => onOtherChange(false, inputValue(e.target.value))}
/>
</div>
)}
If you just have only 2 radio inputs and 2 text inputs, you could handle it like this for 1 radio (you could do the same for other radios in your components).
const [radioValueA, setRadioValueA] = setState(false);
const [textValueA, setTextValueA] = setState(false);
onChangeRadio = (radioType, changedValue) => {
if (radioType === 'A') {
setTextValueA('');
setRadioValueA(changedValue);
} else {
// handle other radio button - should be switch if there are many radio input
}
}
// Radio A
<Input
type="radio"
checked={radioValueA}
onChange={event => onChangeRadio('A', event.target.value)}
/>
// Text A
<Input
type="text"
checked={textValueA}
onChange={event => setTextValueA(event.target.value)}
/>
The main ideas is you must control the input text value then set it to empty (clear) when radio button onChange event trigger

Resources