Checkbox don't show checked - javascript

I'm working with checkbox input. When I click on checbox, checkbox don't show checked but checkbox's value I still get. I use React JS
Simple checkbox
import React from 'react';
import callApi from './../../utils/apiCaller'
import { Link } from 'react-router-dom'
class ProductActionPage extends React.Component {
constructor(props) {
super(props);
this.state = {
id: '',
productStatus: ''
}
}
onChange = (e) => {
var target = e.target;
var name = target.name;
var value = target.type === 'checkbox' ? target.checked : target.value;
this.setState({
[name]: value
});
}
render() {
var statusCheckbox = this.state.productStatus === 'true' ? true : false;
return (
<div className="row">
<div className="col-xs-6 col-sm-6 col-md-6 col-lg-6">
<div className="form-group">
<label>Trang thai: </label>
</div>
<div className="checkbox">
<label>
<input type="checkbox" checked={statusCheckbox} name="productStatus" onChange={this.onChange} />
Con hang
</label>
</div>
<button type="submit" className="btn btn-primary">Luu lai</button>
<Link to="/product/list" className="btn btn-danger ml-5">Huy bo</Link>
</div>
</div>
);
}
}
How can I show checked checkbox?

this.state.productStatus is a boolean value, so your condition will always give you the false, because you are comparing Boolean === String.
Just change
var statusCheckbox = this.state.productStatus === 'true' ? true : false;
to
var statusCheckbox = this.state.productStatus ? true : false; //It doesn't make any sense
Or simply
var statusCheckbox = this.state.productStatus;
Or you can directly use this.state.productStatus,
<input
type="checkbox"
checked={this.state.productStatus}
name="productStatus"
onChange={this.onChange}
/>

Related

"TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator)) "

I am making controlled components in React and I am using states and seting states in forms. But this error occurs.
Here's the code of Quiz.js in which I am making this form for my Quiz app
`
import React from 'react'
export default function Quiz() {
const [questionForm, setQuestionForm] = React.useState(
{questionOne: "",
questionTwo: ""}
)
function handleChange(event) {
const [name , value , type , checked] = event.target
setQuestionForm(prev => {
return {
...prev,
[name]: type === 'checkbox' ? checked : value
}
})
}
return (
<div>
<div className = 'Question'>
<form>
<fieldset>
<legend>What is the capital of UK?</legend>
<label>
Paris
<input
id='Paris'
type="radio"
value='Paris'
name='questionOne'
onChange={handleChange}
checked={questionForm.questionOne === 'Paris'}
/>
</label>
<label>
Moscow
<input
id='Moscow'
type="radio"
value='Moscow'
name='questionOne'
onChange={handleChange}
checked={questionForm.questionOne === 'Moscow'}
/>
</label>
</fieldset>
</form>
<button className='check'>Check Answers</button>
</div>
</div>
)
}
`
I've checked the code again and again but I can't overcome the problem, what's wrong with my code?
replace
const [name , value , type , checked] = event.target
with this
const {name , value , type , checked} = event.target
Demo

Navigating through different pages with onClick & radio buttons - React.js

*Using react-router-dom and react.js
I have two different set of radio buttons. One set has 2 buttons while the other set has 3. I want to navigate to a new page whenever a user clicks on two buttons (one in each set). We have a total of six different outcomes, therefore 6 different pages to navigate to. It seems to work fine but with one problem: it only works when we click on a button for a second time. Example: Clicking on "Messages" & "Global" doesn't work initially and doesn't do anything but then if we click on a different button, then it navigates to the initial set of buttons we clicked.
Does anyone know how to fix this issue? Thank you.
import { useNavigate } from 'react-router-dom';
export default function DisplayHomeOptions() {
let navigate = useNavigate();
const [formData, setFormData] = React.useState({ location: "", selector: "" })
function handleChange(event) {
const { name, value, type, checked } = event.target
setFormData(prevFormData => {
return {
...prevFormData,
[name]: type === "checkbox" ? checked : value
}
})
}
function test() {
return (
formData.location === "National" && formData.selector === "Polls" ? navigate("/np") :
formData.location === "Global" && formData.selector === "Questions" ? navigate("/gq") :
formData.location === "Global" && formData.selector === "Polls" ? navigate("/gp") :
formData.location === "National" && formData.selector === "Messages" ? navigate("/nm") :
formData.location === "National" && formData.selector === "Questions" ? navigate("/nq") :
formData.location === "Global" && formData.selector === "Messages" ? navigate("/gm") : null
)
}
return (
<div>
<fieldset>
<legend>Option #1</legend>
<input
type="radio"
name="location"
value="Global"
onChange={handleChange}
onClick={test}
/>
<label htmlFor="Global">Global</label>
<input
type="radio"
name="location"
value="National"
onChange={handleChange}
onClick={test}
/>
<label htmlFor="National">National</label>
</fieldset>
<fieldset>
<legend>Option #2</legend>
<input
type="radio"
name="selector"
value="Messages"
onChange={handleChange}
onClick={test}
/>
<label htmlFor="Messages">Messages</label>
<input
type="radio"
name="selector"
value="Questions"
onChange={handleChange}
onClick={test}
/>
<label htmlFor="Questions">Questions</label>
<input
type="radio"
name="selector"
value="Polls"
onChange={handleChange}
onClick={test}
/>
<label htmlFor="Polls">Polls</label>
</fieldset>
</div>
)
}```
Issue
The issue is that React state updates aren't immediately processed, they are enqueued and asynchronously processed later. The formData state update from handleChange is not yet available when test function is called as the same time.
Solution
It seems you want the act of navigation to be an effect of selecting from the radio buttons. Move the test function logic into an useEffect hook to issue the imperative navigation.
Example:
export default function DisplayHomeOptions() {
const navigate = useNavigate();
const [formData, setFormData] = React.useState({
location: "",
selector: ""
});
useEffect(() => {
const { location, selector } = formData;
switch (true) {
case location === "National" && selector === "Polls":
navigate("/np");
break;
case location === "Global" && selector === "Questions":
navigate("/gq");
break;
case location === "Global" && selector === "Polls":
navigate("/gp");
break;
case location === "National" && selector === "Messages":
navigate("/nm");
break;
case location === "National" && selector === "Questions":
navigate("/nq");
break;
case location === "Global" && selector === "Messages":
navigate("/gm");
break;
default:
// ignore
}
}, [formData]);
function handleChange(event) {
const { name, value, type, checked } = event.target;
setFormData((prevFormData) => {
return {
...prevFormData,
[name]: type === "checkbox" ? checked : value
};
});
}
return (
<div>
<fieldset>
<legend>Option #1</legend>
<input
type="radio"
name="location"
value="Global"
onChange={handleChange}
/>
<label htmlFor="Global">Global</label>
<input
type="radio"
name="location"
value="National"
onChange={handleChange}
/>
<label htmlFor="National">National</label>
</fieldset>
<fieldset>
<legend>Option #2</legend>
<input
type="radio"
name="selector"
value="Messages"
onChange={handleChange}
/>
<label htmlFor="Messages">Messages</label>
<input
type="radio"
name="selector"
value="Questions"
onChange={handleChange}
/>
<label htmlFor="Questions">Questions</label>
<input
type="radio"
name="selector"
value="Polls"
onChange={handleChange}
/>
<label htmlFor="Polls">Polls</label>
</fieldset>
</div>
);
}
An optimization may be to declare a Map of target paths from the location and selector values as keys.
const navTarget = {
National: {
Messages: "/nm",
Polls: "/np",
Questions: "/nq",
},
Global: {
Messages: "/gm",
Polls: "/gp",
Questions: "/gq",
}
}
...
useEffect(() => {
const { location, selector } = formData;
if (location && selector) {
const target = navTarget[location][selector];
if (target) {
navigate(target);
}
}
}, [formData]);
onClick event fires before onChange event. To account for this, you could move navigation into the onChange event handler.

React form wrong radio values

I have this modalWindow Component, with a form with a preselected "small" option:
import React from "react";
import pizzaStore from "./stores/PizzaStore";
import { observer } from "mobx-react-lite";
import cartStore from "./stores/CartStore";
import { action } from "mobx";
function ModalWindowComponent({ activeModal, setActiveModal }: any) {
const [price, setPrice] = React.useState(pizzaStore.modalProps.price);
console.log(price);
const handlePriceChange = (opt: string) => {
opt === "small"
? setPrice(pizzaStore.modalProps.price)
: opt === "medium"
? setPrice(pizzaStore.modalProps.price * 1.5)
: setPrice(pizzaStore.modalProps.price * 2);
};
const [selectedOption, setSelectedOption] = React.useState("small");
const setClose = () => {
setSelectedOption("small");
setActiveModal(false);
};
let fixedSize = pizzaStore.size;
let size =
selectedOption === "small"
? fixedSize
: selectedOption === "medium"
? fixedSize * 1.5
: fixedSize * 2;
let obj = {
modalName: pizzaStore.modalProps.name,
modalDesc: pizzaStore.modalProps.description,
modalSize: size,
modalPrice: price,
modalImage: pizzaStore.modalProps.imageUrl,
};
return (
<div
className={activeModal ? "modal active" : "modal"}
onClick={() => {
setActiveModal(false);
setSelectedOption("small");
}}
>
<div
className="modal-content"
onClick={(e) => {
e.stopPropagation();
}}
>
<div className="modal-content-header">
<button onClick={() => setClose()}>Close</button>
</div>
<img
src={pizzaStore.modalProps.imageUrl}
className="modal-content-img"
/>
<p className="modal-content-pizza-name">{pizzaStore.modalProps.name}</p>
<p className="modal-content-pizza-desc">
{pizzaStore.modalProps.description}
</p>
<p className="modal-content-pizza-size">{size}см</p>
<p className="modal-content-pizza-weight">
{pizzaStore.setWeight(selectedOption)}грамм
</p>
<p className="modal-content-pizza-price">{price}Руб.</p>
<form
className="modal-content-sizes-form"
onSubmit={(e: any) => {
cartStore.handleSubmitForm(e, obj);
}}
>
<label>
<input
name="radio-size"
value="small"
type="radio"
onChange={(e) => {
setSelectedOption(e.target.value);
console.log(selectedOption);
handlePriceChange(selectedOption);
}}
checked={selectedOption === "small"}
className="modal-content-sizes-form-option"
/>
Маленькая
</label>
<label>
<input
name="radio-size"
value="medium"
type="radio"
onChange={(e) => {
setSelectedOption(e.target.value);
console.log(selectedOption);
handlePriceChange(selectedOption);
}}
checked={selectedOption === "medium"}
className="modal-content-sizes-form-option"
/>
Средняя
</label>
<label>
<input
name="radio-size"
value="big"
type="radio"
onChange={(e) => {
setSelectedOption(e.target.value);
console.log(selectedOption);
}}
checked={selectedOption === "big"}
className="modal-content-sizes-form-option"
/>
Большая
</label>
<button
onClick={() => {
setClose();
console.log(cartStore.cartItems);
}}
>
Добавить
</button>
</form>
</div>
</div>
);
}
export default observer(ModalWindowComponent);
The selectedOption state should update when a radiobutton is clicked.
however, if I try to log in to the console it gives the wrong values.
For example, when you click the medium valued radio button the console logs "small". The other problem is that the price state doesn't update accordingly with the selected option state. I don't quite understand what is wrong.
That's because state update is batching and asynchronous
You setSelectedOption and handlePriceChange in the same function which cause the issue that you won't get the latest update selectedOption
So you would use the original value like so:
onChange={(e) => {
setSelectedOption(e.target.value);
console.log(selectedOption);
handlePriceChange(e.target.value);
}}
Or having a useEffect waiting for selectedOption to change before calling handlePriceChange:
useEffect(() => {
handlePriceChange(selectedOption);
}, [selectedOption]);
setSelectedOption actually doesn't change the value of selectedOption in your onChange handler. My guess is, it always logs the previous value to the console.
To fix this, store e.target.value in a variable and log that.

How to change the state of the checkbox using a method?

I need to create a method and change the state of the checkbox from checked to unchecked and vice versa by calling a method.
onEventListener: (event,props) => {
if (event.key === " ") {
console.log ("Check box is "+ !event.target.checked );
props.onEventListener({onChecked: !event.target.checked});
}
onChecked will be used to change the state , It is a boolean .
render (
<div>
<input
type="checkBox"
onKeyDown={props.onEventListener}
defaultChecked = {props.onChecked}
/>
</div>
)
From the official documentation of React.
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
This handles state changes both for checkboxes and text inputs.

What is the proper way to use radio in React? The button gets frozen once checked

I'm using state to control my component, and I'm not sure what part of the following code is causing the code to button to freeze once checked.
This is the constructor:
constructor(props) {
super(props);
this.state = {
firstName: '',
inPerson: false,
onlineMedium: true,
};
}
This function should handle change:
handleFormChange = (event) => {
const target = event.target;
if (target.name === "inPerson" || target.name === "onlineMedium") {
const value = !this.state[target.name]
const name = target.name;
this.setState({
[name]: value
});
}
else {
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
}
This renders the component:
render() {
return (
<>
<label className="tutor-add-label">
First name
<input
className="tutor-add-input"
type="text"
name="firstName"
value={this.state.firstName}
onChange={this.handleFormChange}
/>
</label>
<div className="medium">
<input
type="radio"
id="online"
name="onlineMedium"
checked={this.state.onlineMedium}
onChange={this.handleFormChange}
/>
<label htmlFor="online">online</label>
<input
type="radio"
id="person"
name="inPerson"
checked={this.state.inPerson}
onChange={this.handleFormChange}
/>
<label htmlFor="person">In person</label>
</div>
</>
)
}
Edit: As per the comment below, please let me know if there is another way to select/unselect radio that works better. I was following this http://react.tips/radio-buttons-in-react-16/
Update: It seems that the click doesn't happen (after the first click)for some reason. Does that seem to point in any direction?
This is what worked for me:
Changing the event handler from onChange to onClick and using the following to control state:
if (target.name === "onlineMedium" || target.name === "inPerson") {
if (event.target.checked && !this.state[target.name]) {
this.setState({
[target.name]: true,
})
}
else if (event.target.checked && this.state[target.name]) {
this.setState({
[target.name]: false,
})
}
}
Credit: it was inspired by this answer: https://stackoverflow.com/a/57147343/10813256

Categories

Resources