React controlled radio buttons not being checked - javascript

I have a child component that receives props from a parent. In the child component it renders a couple radio buttons like this:
<div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="1"
checked={this.props.value === "1"}
/>
True
</label>
</div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="0"
checked={this.props.value === "0"}
/>
False
</label>
</div>
</div>
handleInputChange just calls a parent method like so:
_handleInputChange(e) {
this.props.handleChange(e);
}
that will set the state of the parent component to the value selected in the radio buttons (i.e. "1" or "0"). The issue im having is that the checked conditionals return the correct props, but they function strangely. It almost seems like when the radio input receives a new prop value, it doesn't re render with checked. When the component first renders, the props.value is an empty string. When a user selects a radio button it changes the state of the parent component with _handleInputChange and then sends that value back down for the conditionals.

Thanks to some of the help here and on IRC I figured out it was a preventDefault in my event handler. After removing that it worked perfectly!

You must use state for checked property if you want react re-render radio button.
Example:
<div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="1"
checked={this.state.radioButton1}
/>
True
</label>
</div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={this._handleInputChange}
value="0"
checked={this.state.radioButton2}
/>
False
</label>
</div>
</div>
You also set value for state like this (alternatively, you can initialize it with getInitialState):
this.setState({
radioButton1 : props.value ==="1",
radioButton2 :props.value ==="0"
});
And in _handleInputChange function you're able to know that radio button is checked or unchecked by checking it's state.
_handleInputChange(e) {
var isChecked = e.target.value ==="1" ? this.state.radioButton1 : this.state.radioButton2;
this.props.handleChange(e);
}

use bind method to bind context this._handleInputChange.bind(this) in the constructor,or use (e)=>this._handleInputChange(e) on click ,when the event handler executed normally has no context.
or declared as this below,it can bind this automatically:
class ButtonGroup extends Component{
....
_handleInputChange= (e)=>{
...
}
sample below:
class ButtonGroup extends Component {
render() {
return (
<div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={(e) => this._handleInputChange(e)}
value="1"
checked={this.props.value === "1"}
/>
True
</label>
</div>
<div className="radio">
<label>
<input
type="radio"
name="value"
onChange={(e) => this._handleInputChange(e)}
value="0"
checked={this.props.value === "0"}
/>
False
</label>
</div>
</div>
);
}
_handleInputChange(e) {
this.props.handleChange(e);
}
}
class Form extends Component {
constructor(props) {
super(props);
this.state = {value: '1'};
}
render() {
var value = this.state.value;
return <ButtonGroup value={value} handleChange={(e) => this.valueChanged(e)}/>
}
valueChanged(e) {
this.setState({value: e.target.value});
}
}
ReactDOM.render(
<Form />,
document.getElementById('container')
);

Related

Can't select radio buttons when checked status has some logic

I have a couple of checkboxes that are refusing to be checked.
export default function App() {
let model = {};
return (
<div className="App">
<h1>Hello React Radio Buttons</h1>
<p>
Sure the model object is empty, so initially the radio will be
unchecked, but why can't I manually check it?
</p>
<div>
<input type="radio" id="opt1" checked={model.selection === "opt1"} />
<label htmlFor="opt1">Option 1</label>
</div>
<div>
<input type="radio" id="opt2" checked={model.selection === "opt2"} />
<label htmlFor="opt2">Option 2</label>
</div>
</div>
);
}
Here is a sandbox link.
The above is a simple test scenario, but I am glad I was able to replicate the problem.
The real scenario is I am trying to maintain the status of what radio button was checked when I come back to the page from an error state (i.e. form was submitted, there were errors, I want to come back to the page and maintain the selections).
Because your model does't have selection key. It's better to use useStates hook same as bellow:
export default function App() {
let model = {};
const [checked1, setChecked1] = useState(model.selection === "opt1");
const [checked2, setChecked2] = useState(model.selection === "opt2");
return (
<div className="App">
<h1>Hello React Radio Buttons</h1>
<p>
Sure the model object is empty, so initially the radio will be
unchecked, but why can't I manually check it?
</p>
<div>
<input
type="radio"
id="opt1"
onChange={() => setChecked1(!checked1)}
checked={checked1}
/>
<label htmlFor="opt1">Option 1</label>
</div>
<div>
<input
type="radio"
id="opt2"
onChange={() => setChecked2(!checked2)}
checked={checked2}
/>
<label htmlFor="opt2">Option 2</label>
</div>
</div>
);
}

React radio button button checked attribute not working

I have a react component that resembles a radio button input section. I have the checked attribute on each radio input set to a true or false expression, but it does not end up working when I run it.
Any idea on why the item isn't being lit up when a new item is selected? When I log the expression (console.log), I get the correct result.
My code looks like this:
class MyClass extends Component {
constructor(props) {
super(props);
this.state = {
currentItem: 1,
}
}
updateCurrentItem = (event) => {
let key = `${event.currentTarget.id}`;
this.currentItem = key;
console.log(!(1 % this.currentItem));
}
isOn(id) {
return (!(id % this.currentItem));
}
render() {
return (
<div className="iconList">
<input type="radio" id="one" name="picker" value="one" checked={this.isOn(1)}/>
<label for="one"><button id={1} onClick={this.updateCurrentItem}>One</button></label>
<input type="radio" id="two" name="picker" value="two" checked={this.isOn(2)}/>
<label for="two"><button id={2} onClick={this.updateCurrentItem}>Two</button></label>
<input type="radio" id="three" name="picker" value="three" checked={this.isOn(3)}/>
<label for="three"><button id={3} onClick={this.updateCurrentItem}><Three</button></label>
<input type="radio" id="four" name="picker" value="four" checked={this.isOn(4)}/>
<label for="four"><button id={4} onClick={this.updateCurrentItem}>Four</button></label>
</div>
);
}
}
export default MyClass;
Any help is much appreciated. Thanks!
You should use this.state and this.setState. Here's a working example:
https://codesandbox.io/s/sleepy-dew-thglz?file=/src/App.js

How to disable a checkbox after executing onChange method?

I want to be able to disable a checkbox once I check on the checkbox and execute the onChange method.
I was able to find a way to do this, but once multiple items are checked only the recently checked checkbox is disabled.
The disable method is inside a component class before the render method
Disable = id => {
document.getElementById(id).disabled = true;
//another method to execute onchange
};
<span>
<input
type="checkbox"
className="form-check-input"
onChange={this.Disable}
value=""
/>
</span>;
The checkbox is inside the render method.
One the user checks the checkbox the checkbox needs to check and disable it self
Some notice points:
use camelCase for function name
use props value to make the checkbox fully controlled
use props disabled to disable input element
set the related state inside the handler function
no need for document.getElementById in your current situation
handler event is not id, if you just need id, pass it as a param this.handler(id)
Demo:
const App = () => {
const [checked, setChecked] = React.useState(false);
const [status, setStatus] = React.useState(true);
const onChangeHandler = () => {
setChecked(!checked);
setStatus(false);
};
return (
<div className="App">
<input
type="checkbox"
value={checked}
disabled={!status}
onChange={onChangeHandler}
/>
</div>
);
};
ReactDOM.render(<App />, 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>
you should have to attach id on element .
let Disable=(id)=>{
if(id){
document.getElementById(id).disabled = true
}
}
<span>
<input type="checkbox" className="form-check-input" onChange="Disable(this.id)" id="one" value=""/>
<input type="checkbox" className="form-check-input" onChange="Disable(this.id)" id="two" value=""/>
<input type="checkbox" className="form-check-input" onChange="Disable(this.id)" id="three" value=""/>
</span>
passing the event in an anonymous arrow function and accepting it as an argument in the eventHandler(component method) and using the event.target there is the appropriate way of doing this in such situations that you need to access the caller.
class Stack extends Component {
Disable = event => {
event.target.disabled = true;
//another method to execute onChange
};
render() {
return (
<span>
<input
type="checkbox"
className="form-check-input"
onChange={event => this.Disable(event)}
value=""
/>
<input
type="checkbox"
className="form-check-input"
onChange={event => this.Disable(event)}
value=""
/>
<input
type="checkbox"
className="form-check-input"
onChange={event => this.Disable(event)}
value=""
/>
</span>
);
}
}

Radio buttons with action and store

I am working with 4 radio buttons where I need to take the 2 options selected by the user and send it to a socket, but first, I need to know how to update the options selected using an action and a store
here the code where you can see the buttons
class BetBehindModal extends Component {
constructor (props) {
super(props);
}
render () {
return (
<div>
<div>
<p>Bet Behind Settings</p>
<p>When seated player Doubles:</p>
<form>
<input type="radio" value="double" name="doubles" /> Always Double my bet <br />
<input type="radio" value="nodouble" name="doubles" /> Never Double my bet
<p>When seated player Splits:</p>
<input type="radio" value="split" name="splits" /> Always Split <br />
<input type="radio" value="nosplit" name="splits" /> Assign bet to 1st hand
</form>
<hr />
<button className="toggleModalBtn" type="submit" onClick={this._confirm}>Confirm</button>
</div>
</div>
);
}
}
export default BetBehindModal;
so, there are 4 options, the user has the right to choose 2 of those 4. I need to send that info to a socket and also to a backend made in Nodejs, but the most important part is, how to work with this with the action and the store?
As far as I understand the question, you having a hard time trying to update the state of your component based on the radio buttons. As a way to do it, you may add onChange handler:
class BetBehindModal extends Component {
constructor (props) {
super(props);
this.onDoublesChange = this.onDoublesChange.bind(this);
this.onSplitsChange = this.onSplitsChange.bind(this);
}
render () {
return (
<div>
<div>
<p>Bet Behind Settings</p>
<p>When seated player Doubles:</p>
<form>
<input type="radio" value="double" name="doubles" onChange={this.onDoublesChange}/> Always Double my bet <br />
<input type="radio" value="nodouble" name="doubles" onChange={this.onDoublesChange}/> Never Double my bet
<p>When seated player Splits:</p>
<input type="radio" value="split" name="splits" onChange={this.onSplitsChange}/> Always Split <br />
<input type="radio" value="nosplit" name="splits" onChange={this.onSplitsChange}/> Assign bet to 1st hand
</form>
<hr />
<button className="toggleModalBtn" type="submit" onClick={this._confirm}>Confirm</button>
</div>
</div>
);
}
onDoublesChange({ target }) {
if (target.checked) this.setState({ doubles: target.value });
}
onSplitsChange({ target }) {
if (target.checked) this.setState({ splits: target.value });
}
}
export default BetBehindModal;

In React, how to use one method to toggle states for multiple checkboxes values

_toggleValue: function(state) {
//?? how to do it
//this.setState(???);
},
render() {
<div>
<form>
<input type="checkbox" onChange={this._toggleValue.bind(null, this.state.a)} />
<input type="checkbox" onChange={this._toggleValue.bind(null, this.state.b)} />
<input type="checkbox" onChange={this._toggleValue.bind(null, this.state.c)} />
</form>
</div>
}
There are quite lot checkboxes in the form, currently, what I am doing is to define one method for each checkbox. How can I define one method which can be used by all the checkboxes.
Many thanks in advance
You could use the LinkedStateMixin.
Your checkboxes would look something like this:
<input type='checkbox' checkedLink={this.linkState('a')}/>
<input type='checkbox' checkedLink={this.linkState('b')}/>
<input type='checkbox' checkedLink={this.linkState('c')}/>
This will automatically keep the values of the checkboxes a, b and c up to date with the state variables.
You can use an id on your checkboxes and retrieve it from event.target.id that is passed to onChange handler as below:
_toggleValue: function(event) {
var state = this.state[event.target.id];
},
render: function() {
return (
<div>
<form>
<input type="checkbox" id={1} onChange={this._toggleValue}/>
<input type="checkbox" id={2} onChange={this._toggleValue}/>
<input type="checkbox" id={3} onChange={this._toggleValue}/>
</form>
</div>
)
}
I did it this way:
toggleCheckbox(name, event) {
let change = !this.state[name];
this.setState({name: change});
}
<input type="checkbox" name="active" defaultChecked={this.state.active} onChange={this.toggleCheckbox.bind(this, 'active')} />
<input type="checkbox" name="shared" defaultChecked={this.state.shared} onChange={this.toggleCheckbox.bind(this, 'shared')} />
Note the "defaultChecked" and that I'm not using the preventDefault() statement.

Categories

Resources