Radio buttons in react not keeping checked - javascript

I'm building a form in react and when the user click on the first radio button, the second questions appears.
const [visible1, setVisible1] = useState(false);
const [visible2, setVisible2] = useState(false);
//Question1
const [q1label, setQ1label] = useState();
const [q1opt1, setQ1opt1] = useState();
const [q1opt2, setQ1opt2] = useState();
//Question2
const [q2label, setQ2label] = useState();
const [q2opt1, setQ2opt1] = useState();
const [q2opt2, setQ2opt2] = useState();
const [q2opt3, setQ2opt3] = useState();
const handleQuestions = async e => {
e.preventDefault();
try {
await axios.post(QuestionsUrl, {
language: token,
policyid: token1
})
.then((response) => {
//Question1
setQ1label((response.data?.questions[0].question_label));
setQ1opt1((response.data?.questions[0].question_options[0].option_text));
setQ1opt2((response.data?.questions[0].question_options[1].option_text));
//Question2
setQ2label((response.data?.questions[1].question_label));
setQ2opt1((response.data?.questions[1].question_options[0].option_text));
setQ2opt2((response.data?.questions[1].question_options[1].option_text));
setQ2opt3((response.data?.questions[1].question_options[2].option_text));
} catch(error) {
console.log(error);
}
};
const [selectedRadioButton, setSelectedRadioButton] = useState('');
const [selectedRadioButton1, setSelectedRadioButton1] = useState('');
return (
<>
<form onSubmit={handleQuestions} style={{width:'100%'}}>
<>
<QuestionWrapper id='1'>
<Col100><label><h3>{q1label}</h3></label></Col100>
<Col10><RadioFields value={q1opt1} type="radio" name="radio" id="radiobtn" className='martop'
checked={selectedRadioButton === q1opt1}
onChange={e => {
setQ1opt1(e.target.value);
setSelectedRadioButton(q1opt1);
setVisible1(true);
setVisible16(false);
}} /></Col10><Col90><label>{q1opt1}</label></Col90>
<Col10><RadioFields value={q1opt2} type="radio" name="radio" id="radiobtn" className='martop'
checked={selectedRadioButton === q1opt2}
onChange={e => {
setQ1opt2(e.target.value);
setSelectedRadioButton(q1opt2);
setVisible1(false);
setVisible2(false);
setVisible16(true);
}} /></Col10><Col90><label>{q1opt2}</label></Col90>
</QuestionWrapper>
{visible1 &&
<QuestionWrapper id='2'>
<Col100><label><h3>{q2label}</h3></label></Col100>
<Col10><RadioFields value={q2opt1} type="radio" name="radio" id="radiobtn" className='martop'
checked={selectedRadioButton1 === q2opt1}
onChange={e => {
setQ2opt1(e.target.value);
setSelectedRadioButton1(q2opt1);
setVisible2(true);
}} /></Col10><Col90><label>{q2opt1}</label></Col90>
<Col10><RadioFields value={q2opt2} type="radio" name="radio" id="radiobtn" className='martop' /></Col10><Col90><label>{q2opt2}</label></Col90>
<Col10><RadioFields value={q2opt3} type="radio" name="radio" id="radiobtn" className='martop' /></Col10><Col90><label>{q2opt3}</label></Col90>
</QuestionWrapper>
}
</>
</form>
</>
)
}
So, when clicking on one of the options on the second set of radio buttons (QuestionWrapper id='2'), the radio button from the first question becomes empty and not checked.
Any idea?
#Sagar, I followed your suggestion and changed the codes. I still can't get the question 2 radio button filled when ticked.
Not sure what is wrong with the form at this time.

Related

React multi step form with radio buttons

React newbie here.
I'm trying to make a multi-step form to get some details from the user and for some of the nested views, there are only radio buttons. The handleChange works fine on text type but how can I handle radio buttons?
React does not render the radio button that is used to render in AngularJS, so I am a bit confused. I can choose multiple radio button and all of them looks like checkboxes instead of choosing only one
MainForms.js
export class UserForm extends Component {
state = {
step: 1,
tema: '',
area: '',
type: '',
name: ''
};
// Proceed to next step
nextStep = () => {
const { step } = this.state;
this.setState({
step: step + 1
});
};
// Go back to prev step
prevStep = () => {
const { step } = this.state;
this.setState({
step: step - 1
});
};
// Handle fields change
handleChange = input => e => {
this.setState({ [input]: e.target.value });
console.log(e.target.value)
};
render() {
const { step } = this.state;
const { area, name, type, tema} = this.state;
const values = { area, name, type, tema};
switch (step) {
case 1:
return (
<FormUserDetails
nextStep={this.nextStep}
handleChange={this.handleChange}
values={values}
/>
);
FormUserDetails.js
export class FormUserDetails extends Component {
continue = (e) => {
e.preventDefault();
this.props.nextStep();
};
back = (e) => {
e.preventDefault();
this.props.prevStep();
}
render() {
const { handleChange } = this.props;
return (
<div className="box item2">
<div className="radio">
<label>
<input
type="radio"
onChange={handleChange}
/>
Basic
</label>
</div>
);
}
}
form example
For the radio input not to "work like an checkbox" they all need the same name in this case its "yyy".
<div className="box item2">
<div className="radio">
<label>
<input
type="radio"
name="yyy"
value="123"
onChange={handleChange}
/>
Basic
</label>
</div>
<div className="radio">
<label>
<input
type="radio"
name="yyy"
value="456"
onChange={handleChange}
/>
Basic
</label>
</div>
</div>
Your handleChange receives the event and not some input prop. To see if the radio input is checked or not you can use the checked property.
handleChange = (e) => {
const target = e.target;
// do whatever you want with the state :)
this.setState({ [target.name]: target.value });
};
I'm not 100% sure if I understand your question correct and if my answer helps you, but what I have made in my solution is something like this:
export const RadioButtonInputField = ({label, onChangeOut}) => {
const [state, setState] = useState(true);
const setOnChange = (value) => {
onChangeOut({value: value});
setState(value);
};
return (
<div className={`dynamic-input-container`}>
<div className={'radio-button-wrapper'}>
<p className={'radio-title'}>{label}</p>
<label className={'radio-label first-radio-label'}>
<input
type='radio'
value={true}
checked={state === true}
className={'radio-input'}
onChange={() => {
setOnChange(true);
}}
/>
<span className={'radio-btn-label'}>Yes</span>
</label>
<br />
<label className={'radio-label'}>
<input
type='radio'
value={false}
checked={state === false}
className={'radio-input'}
onChange={() => {
setOnChange(false);
}}
/>
<span className={'radio-btn-label'}>No</span>
</label>
</div>
</div>
);
}

How to show error if client did not click check, but with not default value

I am trying to show error message if client did not click checkbox, but it shows the error message by default.
How do I manage to show it only after submission?
const InputForm=()=>{
const [value ,setValue] = useState("");
const [check,setCheck] = useState(null)
const getValue=(e)=>{
setValue(e.target.value);
}
const getCheck=(e)=>{
setCheck(e.target.checked);
}
const handleSubmit=(e)=>{
e.preventDefault();
const emailValidator =/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/
if (value.match(emailValidator)) {
console.log("Valid");
}else{
console.log("Invalid");
}
};
return(
<form className="inputForm" onSubmit={handleSubmit}>
<div className="tos" >
<label className="container">
<span>I agree to <strong>terms of service</strong></span>
<input type="checkbox" onChange={getCheck}/>
<span className="checkmark" ></span>
</label>
<p style={check?{display:"none"}:{display:"block",color:"red"}}>You must accept the terms and conditions</p>
</div>
<Footer/>
</form>
)
};
import { useEffect, useState } from "react";
export default function App() {
const [checked, setChecked] = useState(null);
const [error, setError] = useState(false);
useEffect(() => {
checked && setError(false);
}, [checked, setError]);
const handleSubmit = (e) => {
e.preventDefault();
if (!checked) {
setError(true);
} else {
// do what you want
}
};
return (
<form className="inputForm" onSubmit={handleSubmit}>
<div className="tos">
<label className="container">
<span>
I agree to <strong>terms of service</strong>
</span>
<input
type="checkbox"
onChange={(e) => setChecked(e.target.checked)}
/>
<span className="checkmark"></span>
</label>
{error && (
<p style={{ color: "red" }}>
You must accept the terms and conditions
</p>
)}
</div>
<button type="submit">submit</button>
</form>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Here is a solution :
https://codesandbox.io/s/crimson-field-m6j5h?file=/src/App.js
You should have a separate state for the error and render the message only if that state is truthy.
That state should be set when calling you handleSubmit function.
To remove the error message when the checkbox is checked, you can listen to it in a useEffect hook.

How to set the initial value of useState with the value of another state set in a useEffect hook?

I get user data from Firestore in a useEffect hook and then put the data in a state. This part works fine.
const [profile, setProfile] = useState("")
useEffect(() => {
// Get user profile data from firestore..
setProfile(userData)
}, [])
I have HTML radio inputs where user can change their gender but I need to set the initial gender (one they choose during sign-up) with a state.
const defaultGender = profile.gender
const [gender, setGender] = useState(defaultGender)
<input onChange={e => setGender(e.target.value)} type="radio" id="Man" name="gender" value="Man" checked={defaultGender === "Man"} /> <label htmlFor="Man">Man</label>
<input onChange={e => setGender(e.target.value)} type="radio" id="Woman" name="gender" value="Woman" checked={defaultGender === "Woman"} />
<label htmlFor="Woman">Woman</label>
The problem is, with this code, console.log(gender) returns undefined and I can not check (select) a different gender as it is stuck on Man.
Seems like you just need to:
Use gender from the state (not defaultGender) for the checked input's prop.
Update your gender state after the profile state updating.
CodePen
const { useState, useEffect, Fragment } = React;
const Form = () => {
const [profile, setProfile] = useState({});
const [gender, setGender] = useState(profile.gender);
useEffect(() => {
// Assuming you have an async request here...
const profile = { gender: "Woman" };
setProfile(profile);
setGender(profile.gender);
}, []);
return (
<Fragment>
<input
onChange={(e) => setGender(e.target.value)}
type="radio"
id="Man"
name="gender"
value="Man"
checked={gender === "Man"}
/>
<label htmlFor="Man">Man</label>
<input
onChange={(e) => setGender(e.target.value)}
type="radio"
id="Woman"
name="gender"
value="Woman"
checked={gender === "Woman"}
/>
<label htmlFor="Woman">Woman</label>
</Fragment>
);
};
ReactDOM.render(<Form />, document.body);
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>

Push Multiple checkbox data in array in ReactJs?

I need to push the data in array form, from checkbox value.
Code
import React,{ useState,useEffect } from "react";
export default function App() {
const [person, setPerson] = useState([]);
const CheckHandler = () => {
// setPerson(() => { ...person, })
}
useEffect(() => {
//Print data each time the checkbox is "checked" or "unchecked"
console.log(person);
}, [person]);
return (
<>
<input type="checkbox" id="jane" name="jane" value="jane" onClick={() => CheckHandler()} />
<label htmlFor="jane">jane</label><br/>
<input type="checkbox" id="Mike" name="Mike" value="Mike" onClick={() => CheckHandler()} />
<label htmlFor="Mike">Mike</label><br/>
<input type="checkbox" id="board" name="board" value="board" onClick={() => CheckHandler()} />
<label htmlFor="board">board</label><br/>
</>
);
}
What should I do to get my data in array in my console?
sandbox : https://codesandbox.io/s/adoring-rgb-27wkt
Do you want like this and I also added add and removed filter
const CheckHandler = (e) => {
const value = e.target.value;
setPerson((prev) =>
person.includes(value)
? prev.filter((cur) => cur !== value)
: [...prev, e.target.value]
);
};
FULL CODE
import React, { Fragment, useState, useEffect } from "react";
export default function App() {
const [person, setPerson] = useState([]);
const CheckHandler = (e) => {
setPerson((prev) => [...prev, e.target.value]);
};
useEffect(() => {
//Print data each time the checkbox is "checked" or "unchecked"
console.log(person);
}, [person]);
return (
<Fragment>
<input
type="checkbox"
id="jane"
name="jane"
value="jane"
onClick={CheckHandler}
/>
<label htmlFor="jane">jane</label>
<br />
<input
type="checkbox"
id="Mike"
name="Mike"
value="Mike"
onClick={CheckHandler}
/>
<label htmlFor="Mike">Mike</label>
<br />
<input
type="checkbox"
id="board"
name="board"
value="board"
onClick={CheckHandler}
/>
<label htmlFor="board">board</label>
<br />
</Fragment>
);
}
Codesandbox: https://codesandbox.io/s/twilight-hill-lh9bv?file=/src/App.js:0-986

My Balance States Throws Balance.map is not a function error?

I'm making a simple React app that keeps track of expenses, income, and balances. I'm using a state hook called Balance that is the sum of all the input state. The issue is React throws a Balance.map is not a function. So, I'm unable to show what the total would be when the user enters all their input.
Here's the full code:
export default function App() {
const [Balance, setBalance] = useState([]);
const [Income, setIncome] = useState(0);
const [Expense, setExpense] = useState(0);
const [Input, setInput] = useState([]);
console.log(typeof Balance);
const handleChange = (e) => {
setInput(e.target.value);
};
const handleClick = (e) => {
e.preventDefault();
if (Input > 0) {
setIncome(Input);
} else {
setExpense(Input);
}
let val = parseInt(Input);
setBalance(val, ...Balance);
//console.log(...Balance);
setInput("");
};
return (
<div style={{ textAlign: "center", marginTop: "150px" }}>
<form>
<label htmlFor="input"> Please enter value: </label>
<input
name="input"
type="number"
value={Input}
onChange={handleChange}
/>
<button onClick={handleClick}> Submit</button>
</form>
<br />
<h3> My Balance:</h3>
<p>
{Balance.map((i) => {
return i;
})}
</p>
<h3> My Income: {Income}</h3>
<h3> My Expense: {Expense}</h3>
</div>
);
}
I know that the Balance state ,despite it being set as an array, is still an object. I'm assuming the error is coming from there? If so, should setBalance(...Input) work?
as users say in the comments, the problem is the way you update the value of Balance, Here I do some changes in this places:
let val = parseInt(Input, 10); // Here I add the base of parseInt
setBalance([...Balance, val]) Here I let the value as an array in the setBalance
The complete code is:
import React, {useState} from "react";
import "./styles.css";
export default function App() {
const [Balance, setBalance] = useState([]);
const [Income, setIncome] = useState(0);
const [Expense, setExpense] = useState(0);
const [Input, setInput] = useState([]);
console.log(typeof Balance);
const handleChange = (e) => {
setInput(e.target.value);
};
const handleClick = (e) => {
e.preventDefault();
if (Input > 0) {
setIncome(Input);
} else {
setExpense(Input);
}
let val = parseInt(Input, 10);
setBalance([...Balance, val]);
//console.log(...Balance);
setInput("");
};
return (
<div style={{ textAlign: "center", marginTop: "150px" }}>
<form>
<label htmlFor="input"> Please enter value: </label>
<input
name="input"
type="number"
value={Input}
onChange={handleChange}
/>
<button onClick={handleClick}> Submit</button>
</form>
<br />
<h3> My Balance:</h3>
<p>
{Balance.map((i) => {
return i;
})}
</p>
<h3> My Income: {Income}</h3>
<h3> My Expense: {Expense}</h3>
</div>
);
}

Categories

Resources