Radio button cannot return different state - javascript

I am fairly new to developing web app using React.js and Firebase so pardon me if my question doesn't seems relevant.
I have this simple web app where user can choose an option from multiple choices using radio button. When the user finished answering the questions, they will submit their answers and the answers will be submitted to the Firebase.
Now I'm stuck at writing the chosen value to the Firebase. There are 2 issues for me:
1) The radio button can only be clicked once. Meaning that users cannot answer the second question without the first answer being deselected.
2) When I clicked on submit, all the other option returns the same values as the chosen option.
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import logo from './logo.svg';
import './App.css';
import firebase from './firebase.js';
class App extends Component {
constructor(){
super();
this.state = {
owl: '',
house: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render(){
return(
<div>
<ol type="1">
<form onSubmit={this.handleSubmit}>
<li><p>What is the name of Harry Potter's owl?</p></li>
<ol type="a">
<div className="radio">
<label>
<li><input type="radio" name="owl" value="hedwig" checked={this.state.owl === "hedwig"} onChange={this.handleChange}/>
Hedwig<br></br></li>
<li><input type="radio" name="owl" value="ron" checked={this.state.owl === "ron"} onChange={this.handleChange}/>
Ron <br></br></li>
<li><input type="radio" name="owl" value="brian" checked={this.state.owl === "brian"} onChange={this.handleChange}/>
Brian</li>
<br></br>
<br></br>
</label>
</div>
</ol>
<li><p>What is the name of Cho Chang's house?</p></li>
<ol type="a">
<div className="radio">
<label>
<li><input type="radio" name="house" value="gryffindor" checked={this.state.house === "gryffindor"} onChange={this.handleChange}/>
Gryffindor<br></br></li>
<li><input type="radio" name="house" value="slytherin" checked={this.state.house === "slytherin"} onChange={this.handleChange}/>
Slytherin <br></br></li>
<li><input type="radio" name="house" value="ravenclaw" checked={this.state.house === "ravenclaw"} onChange={this.handleChange}/>
Ravenclaw</li>
<br></br>
<br></br>
</label>
</div>
</ol>
<button>Submit!</button>
</form>
</ol>
</div>
)
}
handleChange = (e) =>{
this.setState({
owl: e.target.value,
house: e.target.value
});
}
handleSubmit = (e) =>{
e.preventDefault();
const itemsRef = firebase.database().ref('answers');
const item = {
owl: this.state.owl,
house: this.state.house
}
itemsRef.push(item);
this.setState({
owl: '',
house: ''
});
}
}
export default App;

I found the answer already, after 12 hours of searching and staring at the code.
I just needed to set a unique name for the onChange method. Here's what I have done.
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import logo from './logo.svg';
import './App.css';
import firebase from './firebase.js';
class App extends Component {
constructor(){
super();
this.state = {
owl: '',
house: ''
};
//owlChange and houseChange are now exclusively for owl and house values respectively
this.owlChange = this.owlChange.bind(this);
this.houseChange = this.houseChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render(){
return(
<div>
<ol type="1">
<form onSubmit={this.handleSubmit}>
<li><p>What is the name of Harry Potter's owl?</p></li>
<ol type="a">
<div className="radio">
<label>
<li><input type="radio" name="owl" value="hedwig" checked={this.state.owl === "hedwig"} onChange={this.owlChange}/>
Hedwig<br></br></li>
<li><input type="radio" name="owl" value="ron" checked={this.state.owl === "ron"} onChange={this.owlChange}/>
Ron <br></br></li>
<li><input type="radio" name="owl" value="brian" checked={this.state.owl === "brian"} onChange={this.owlChange}/>
Brian</li>
<br></br>
<br></br>
</label>
</div>
</ol>
<li><p>What is the name of Cho Chang's house?</p></li>
<ol type="a">
<div className="radio">
<label>
<li><input type="radio" name="house" value="gryffindor" checked={this.state.house === "gryffindor"} onChange={this.houseChange}/>
Gryffindor<br></br></li>
<li><input type="radio" name="house" value="slytherin" checked={this.state.house === "slytherin"} onChange={this.houseChange}/>
Slytherin <br></br></li>
<li><input type="radio" name="house" value="ravenclaw" checked={this.state.house === "ravenclaw"} onChange={this.houseChange}/>
Ravenclaw</li>
<br></br>
<br></br>
</label>
</div>
</ol>
<button>Submit!</button>
</form>
</ol>
</div>
)
}
owlChange = (e) =>{
this.setState({
owl: e.target.value
});
}
houseChange = (e) =>{
this.setState({
house: e.target.value
});
}
handleSubmit = (e) =>{
e.preventDefault();
const itemsRef = firebase.database().ref('answers');
const item = {
owl: this.state.owl,
house: this.state.house
}
itemsRef.push(item);
this.setState({
owl: '',
house: ''
});
}
}
export default App;

Related

Conditional visibility in a react component

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;

React update components issue

I have 3 components: App, CV and EXP_FORM.
APP have state where i store data from EXP_FORM and after that i render it by CV component. Issue is when i type in input fields in EXP_FORM CV updates it in one step behind.
for example: if i type in position input field in EXP_FORM "soft" in CV i will got "sof"
app.js
import React,{Component} from "react";
import CV from "./components/CV"
import EXP_FORM from "./components/Exp_form";
class App extends Component {
constructor(){
super()
this.state = {
name: '',
email: '',
phone: '',
//educationLs:[],
experienceLs:[{id:0}],
}
this.handleChange = this.handleChange.bind(this)
this.handleExp = this.handleExp.bind(this)
}
form_style = {
display: 'grid'
}
handleChange(event){
this.setState({
[event.target.id] : event.target.value
})
}
handleExp = (exp) => {
this.setState({
experienceLs: this.state.experienceLs.map(u => u.id !== exp.id ? u : exp),
})
}
render(){
const {name, email, phone, educationLs,experienceLs} = this.state
return (
<div>
<form style={this.form_style}>
<label htmlFor='nameInput'>Name: </label>
<input type='text' id='name' onChange={this.handleChange}/>
<label htmlFor='emailInput'>Email: </label>
<input type='text' id='email' onChange={this.handleChange}/>
<label htmlFor='phoneInput'>Phone: </label>
<input type='text' id='phone' onChange={this.handleChange}/>
</form>
<EXP_FORM id={0} callback={this.handleExp}/>
<div>
<CV name={name} email={email} phone={phone} exp={experienceLs} />
</div>
</div>
)
}
}
export default App;
EXP_FORM.js
import React from 'react'
class EXP_FORM extends React.Component {
constructor(props){
super(props)
this.state = {
id: props.id,
position: '',
company: '',
city:'',
from: '',
to: ''
}
this.handleChange = this.handleChange.bind(this)
}
form_style = {
display:'grid'
}
handleChange(event){
this.setState({
[event.target.name] : event.target.value
})
}
onTrigger = () => {
this.props.callback(this.state)
}
onChangeEvents = (event) => {
this.handleChange(event)
this.onTrigger()
}
render(){
const {position} = this.state
return(
<div>
<form style={this.form_style} onChange={this.onChangeEvents}>
<label htmlFor='position'>Position: {position}</label>
<input type='text' name='position'/>
<label htmlFor='company'>Company: </label>
<input type='text' name='company'/>
<label htmlFor='city'>City: </label>
<input type='text' name='city'/>
<label htmlFor='from'>From: </label>
<input type='text' name='from'/>
<label htmlFor='to'>To: </label>
<input type='text' name='to'/>
</form>
</div>
)
}
}
export default EXP_FORM
CV.js
import React from "react"
const CV = (props)=>{
const exp = props.exp.map((e) =>
<div key={e.id}>
<p>position: {e.position}</p>
<p>in {e.company}</p>
<p>From {e.from} until {e.to}</p>
<p>city:{e.city}</p>
</div>);
return(
<div>
<h1>Name: <span>{props.name}</span></h1>
<h1>Email: <span>{props.email}</span></h1>
<h1>Phone: <span>{props.phone}</span></h1>
<h1>Experience:</h1>
{exp}
</div>
)
}
export default CV
whats wrong ?

Display input box if selecting a specific radio button

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>
);
};

React checkboxes "Cannot read property" error

i am trying checkboxes (component) in react and trying to get all the variables checked. I wrote the code as:
import React, { Component } from 'react'
import {
Card,
Container,
CardBody,
Form,
FormGroup,
Label,
Input,
Button,
} from "reactstrap";
export default class Chk extends React.Component {
states={
Colornames:{
ship:false,
cabin:false,
grade:false,
rate:false,
marketing:false,
image:false
}
}
chkClick = (e) => {
var {name, checked} = e.target;
var name = e.target.name;
var checked = e.target.checked;
console.log("xxxxx", e.Colornames)
this.setState((e) => {
var SelectedSport = e.Colornames;
return SelectedSport[name]=checked;
});
};
render() {
var displaySports = Object.keys(this.states.Colornames);
console.log("aaaaaa", displaySports)
return (
<div>
<center>
<input type="checkbox" name="ship" onChange={this.chkClick}/> Ship
<input type="checkbox" name="cabin" onChange={this.chkClick}/> Cabin
<input type="checkbox" name="grade" onChange={this.chkClick}/> Grade
<input type="checkbox" name="rate" onChange={this.chkClick}/> Rate
<input type="checkbox" name="marketing" onChange={this.chkClick}/> Marketing
<input type="checkbox" name="image" onChange={this.chkClick}/> Image
</center>
</div>
)
}
}
This is giving error:
TypeError: Cannot read property 'Colornames' of null
i feel its all fine with the code.
Finally i need all the checkboxes value (checked: true/false) so that i can do a search from the data as per the checkboxes checked
BTW i am using a mac machine with chrome browser.
Just went through the problem statement again, and found out that the state initialisation wasn't correct. While using the React Class Components, the state should be initialised inside the constructor. I have tried to make the function chkClick a little simpler and everything is working as per exepctation.
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
colornames: {
ship: false,
cabin: false,
grade: false,
rate: false,
marketing: false,
image: false
}
}
}
chkClick = (e) => {
var { name, checked } = e.target;
console.log(name, checked);
this.setState((prevState) => {
return {
colornames: {
...prevState.colornames,
[name]: checked
}
}
});
}
render() {
return (
<div>
<center>
<input type="checkbox" name="ship" onChange={this.chkClick} /> Ship
<input type="checkbox" name="cabin" onChange={this.chkClick} /> Cabin
<input type="checkbox" name="grade" onChange={this.chkClick} /> Grade
<input type="checkbox" name="rate" onChange={this.chkClick} /> Rate
<input type="checkbox" name="marketing" onChange={this.chkClick} /> Marketing
<input type="checkbox" name="image" onChange={this.chkClick} /> Image
</center>
</div>
)
}
}

In react, how do select/checked the radio buttons?

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>
);
}
}

Categories