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;
Related
Example Form So Far
This is my current code that works, without any checkbox handling started.
import React, { useState } from "react";
import "../admin/SysHealthForm.scss";
export default function SysHealthForm() {
const [input, setInput] = useState({
header: "",
content: "",
eta: "",
});
//When any change is registered, update the Name + Value with target.
//Return previous text and display as name: entered value
function handleChange(e) {
const { name, value } = e.target;
setInput((prevInput) => {
return {
...prevInput,
[name]: value,
};
});
}
//Stop Page Refreshing and Console.log the JSON
function handleClick(e) {
e.preventDefault();
console.log(input);
}
return (
<div className="widgit-syshealth">
<h2>System Health</h2>
<form>
<input
name="header"
placeholder="Header"
autoComplete="off"
onChange={handleChange}
value={input.header}
required
></input>
<textarea
name="content"
placeholder="Message"
autoComplete="off"
onChange={handleChange}
value={input.content}
required
></textarea>
<div className="form-school-check">
<div>
<input type="checkbox" id="syshpcb1" value="Fosseway"></input>
<label htmlFor="syshpcb1">Fosse Way</label>
</div>
<div>
<input type="checkbox" id="syshpcb2" value="Mendip"></input>
<label htmlFor="syshpcb2">Mendip</label>
</div>
<div>
<input type="checkbox" id="syshpcb3" value="Nunney"></input>
<label htmlFor="syshpcb3">Nunney</label>
</div>
<div>
<input type="checkbox" id="syshpcb4" value="Hayesdown"></input>
<label htmlFor="syshpcb4">Hayesdown</label>
</div>
<div>
<input type="checkbox" id="syshpcb5" value="Moorlands"></input>
<label htmlFor="syshpcb5">Moorlands</label>
</div>
<div>
<input type="checkbox" id="syshpcb6" value="Cameley"></input>
<label htmlFor="syshpcb6">Cameley</label>
</div>
<div>
<input type="checkbox" id="syshpcb7" value="St Mary's"></input>
<label htmlFor="syshpcb7">St Mary's</label>
</div>
<div>
<input type="checkbox" id="syshpcb8" value="Other"></input>
<label htmlFor="syshpcb8">Other</label>
</div>
</div>
<input
placeholder="ETA For Fix"
onChange={handleChange}
value={input.eta}
name="eta"
></input>
<button type="Submit" onClick={handleClick}>
Submit
</button>
</form>
</div>
);
}
At The Moment, when you submit the data. It logs the header, content and eta etc correctly
but i want it to essentially create an Array of all the checkboxes that are ticked.
I just don't know where i would even begin..
Will be pushing the data back up to a MongoDB Atlas database once recieved.
Thanks
There are two components
WelcomePage.jsx
import { useState } from "react";
import SignUpPage from "./SignUpPage";
function WelcomePage() {
const [signUp, toSignUp] = useState(false);
function signUpClick() {
toSignUp(true);
}
return (
<div>
{signUp ? (
<SignUpPage isOpen={signUp} />
) : (
<div
className="Welcome_page__container animate__animated animate__fadeIn"
id="welcome_page"
>
<h1 className="Welcome_page__title">Welcome to Hotel Review </h1>
<h3 className="Welcome_page__subtitle">Sign in :</h3>
<div className="Welcome_page__wrapper">
<label className="Welcome_page__input-title" htmlFor="welcome_mail">
E-mail:
</label>
<input
className="Welcome_page__input"
id="welcome_mail"
type="mail"
placeholder="Your e-mail..."
/>
<label className="Welcome_page__input-title" htmlFor="welcome_pass">
Password:
</label>
<input
className="Welcome_page__input"
id="welcome_pass"
type="text"
placeholder="Your password..."
/>
<button className="Welcome_page__btn">Login</button>
<button className="Welcome_page__btn" onClick={signUpClick}>
Sign Up
</button>
</div>
</div>
)}
</div>
);
}
export default WelcomePage;
SignUpPage.jsx
function SignUpPage() {
return (
<div className="Welcome_page__container animate__animated animate__fadeIn">
<button>Back...</button>
<h1 className="Welcome_page__title">Welcome to Hotel Review </h1>
<h3 className="Welcome_page__subtitle">Sign up :</h3>
<div className="Welcome_page__wrapper">
<label className="Welcome_page__input-title" htmlFor="welcome_mail">
E-mail:
</label>
<input
className="Welcome_page__input"
id="welcome_mail"
type="mail"
placeholder="Your e-mail..."
/>
<label className="Welcome_page__input-title" htmlFor="welcome_pass">
Password:
</label>
<input
className="Welcome_page__input"
id="welcome_pass"
type="text"
placeholder="Your password..."
/>
<label
className="Welcome_page__input-title"
htmlFor="welcome_pass"
></label>
<input
className="Welcome_page__input"
id="welcome_pass_repeat"
type="text"
placeholder="Repeat password..."
/>
<button className="Welcome_page__btn_2">Sign Up</button>
</div>
</div>
);
}
export default SignUpPage;
Clicking the "Sign Up" button in WelcomePage.jsx using useState navigates to SignUpPage.jsx
Question - How can I return back to WelcomePage.jsx on the "Back" button (I understand that I need to return false back to const [signUp, toSignUp] = useState() , but I don't know how to transfer state from WelcomePage to SignUpPage and vice versa.)
You can pass it via props from parent to child component.
And pass the setState from child component to parent.
import { useState } from "react";
import SignUpPage from "./SignUpPage";
function WelcomePage() {
const [signUp, setSignUp] = useState(false);
function signUpClick() {
toSignUp(true);
}
return (
<>
{signUp ? (
<SignUpPage isOpen={signUp} setOpen={setSignUp} />
) : (
<div>
... component
</div>
)
</>
);
}
export default WelcomePage;
function SignUpPage(props) {
const { isOpen, setOpen } = props;
return (
<>
{isOpen}
<button onClick={setOpen(true)}>Open</button>
<button onClick={setOpen(false)}>Close</button>
</>
);
}
export default SignUpPage;
It randomly started doing this and I am not sure why tho. I have two modals (these are named differently) that are exactly the same but only one is working. The modal I am using is the React-Modal library. The first one works just fine on the home page but the second doesn't at all on an edit details page.
What I did notice is that there is a div placed with an Id of __Next on the home page that is working that places the content of the modal inside but that same exact div does not show up on the other page for the same modal to work.
Below are the two components I am working with and its parent component that houses both
Parent:
import styles from './homeheader.module.css';
import { useRouter } from 'next/router';
import { useState } from 'react';
import NewInvoice from '../invoice/modal/NewInvoice';
import Link from 'next/link';
import { getDatabase, ref, remove } from "firebase/database";
import { database } from '../firebase/firebase';
import EditInvoice from '../invoice/modal/EditInvoice';
export default function HomeHeader(props) {
const [newInvoiceModalIsOpen, setNewInvoiceOpen] = useState(false);
const [editInvoiceModalIsOpen, setEditInvoiceOpen] = useState(false);
const router = useRouter();
const pathName = router.pathname;
const { data, count, id, detail } = props;
function openNewInvoiceModalHandler() {
setNewInvoiceOpen(true)
}
function closeNewInvoiceModalHandler() {
setNewInvoiceOpen(false)
}
function openEditInvoiceModalHandler() {
setEditInvoiceOpen(true)
}
function closeEditInvoiceModalHandler() {
console.log(data)
setEditInvoiceOpen(false)
}
function deleteInvoiceHandler() {
console.log('delete')
console.log(id)
const db = database;
remove(ref(db, 'invoices/' + id))
}
function markAsPaidInvoiceHandler() {
console.log('paid')
}
if (pathName === '/detail/[id]') {
return (
<>
<div className={styles.headerwrapper}>
<Link href="/">
<a>Go back</a>
</Link>
{/* <p>{detail.data.status}</p> */}
<div>
<button onClick={openEditInvoiceModalHandler}>Edit</button>
<button onClick={deleteInvoiceHandler}>Delete</button>
<button onClick={markAsPaidInvoiceHandler}>Mark as Paid</button>
</div>
</div>
<EditInvoice isOpen={editInvoiceModalIsOpen} closeModal={closeEditInvoiceModalHandler} details={detail}/>
</>
)
}
return (
<div className={styles.headerwrapper}>
<div className={styles.leftside}>
<h1 className={styles.header}>Invoices</h1>
<p className={styles.text}>There are {count} total invoices</p>
</div>
<div className="right-side">
<select className={styles.filter} id="filter" placeholder="Filter by status">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
</select>
<button className={styles.button} onClick={openNewInvoiceModalHandler}>New Invoice</button>
</div>
<NewInvoice isOpen={newInvoiceModalIsOpen} closeModal={closeNewInvoiceModalHandler} count={count}/>
</div>
)
}
Child modal component that IS WORKING:
import { useForm } from 'react-hook-form';
import ReactModal from 'react-modal';
import { database } from '../../firebase/firebase';
import { ref, set } from "firebase/database";
import styles from './newinvoice.module.css'
// ReactModal.setAppElement("#__next")
export default function NewInvoice (props) {
const { register, handleSubmit, watch, formState: { errors } } = useForm();
function onSubmit(data) {
const randGen = Math.floor(Math.random() * 9999999);
data.id = randGen;
const db = database;
set(ref(db, '/invoices/' + randGen), {
data: data
})
setTimeout(() => {
window.location.reload(true)
}, 500)
props.closeModal();
}
return (
<>
<ReactModal isOpen={props.isOpen}>
<h1>New Invoice</h1>
<form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
<label>Street Address</label>
<input {...register("senderAddress.street")} />
<label>City</label>
<input {...register("senderAddress.city")} />
<label>Postal Code</label>
<input {...register("senderAddress.postCode")} />
<label>Country</label>
<input {...register("senderAddress.country")} />
<label>Client"s Name</label>
<input {...register("clientName")} />
<label>Client"s Email</label>
<input {...register("clientEmail")} />
<label>Street Address</label>
<input {...register("clientAddress.street")} />
<label>City</label>
<input {...register("clientAddress.city")} />
<label>Postal Code</label>
<input {...register("clientAddress.postCode")} />
<label>Country</label>
<input {...register("clientAddress.country")} />
<label>Invoice Date</label>
<input {...register("createdAt")} />
<label>Payment Terms</label>
<input {...register("paymentTerms")} />
<label>Project Description</label>
<input {...register("description")} />
{/* //Item list goes here */}
<input {...register("items")} />
<input type="submit" placeholder="Submit"/>
</form>
<button onClick={props.closeModal}>Close</button>
</ReactModal>
</>
)
}
Child component that is NOT WORKING:
import { useForm } from 'react-hook-form';
import ReactModal from 'react-modal';
import { database } from '../../firebase/firebase';
import { ref, set } from "firebase/database";
import { useRouter } from 'next/router';
import styles from './newinvoice.module.css'
import { useEffect, useState } from 'react';
ReactModal.setAppElement("#react-modals")
export default function EditInvoice(props) {
const { register, handleSubmit, watch, formState: { errors } } = useForm();
const [formData, setFormData] = useState();
const { isOpen, closeModal, detail } = props;
const router = useRouter();
const id = router.query.id;
const dbLink = `https://invoice-app-3fa85-default-rtdb.firebaseio.com/invoices/${id}.json`;
function onSubmit(data) {
const db = database;
set(ref(db, '/invoices/' + id), {
data: data
})
setTimeout(() => {
window.location.reload(true)
}, 500)
props.closeModal();
}
// function onSubmit(data) {
// console.log(data)
// }
useEffect(() => {
// fectchData();
console.log(formData)
})
const fectchData = async () => {
try {
const res = await fetch(dbLink);
const json = await res.json();
setFormData(json)
} catch (error) {
console.log(error)
}
}
if (!formData) {
console.log('not working')
return <p>Loading....</p>
}
return (
<>
<ReactModal isOpen={true} portalClassName="editInvoiceModal" parentSelector={() => document.querySelector('#react-modals')}>
<h1>Edit Invoice </h1>
<form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
<label>Street Address</label>
<input {...register("senderAddress.street")} defaultValue={detail.senderAddress.street}/>
{/* <label>City</label>
<input {...register("senderAddress.city")} defaultValue={formData.senderAddress.city}/>
<label>Postal Code</label>
<input {...register("senderAddress.postCode")} defaultValue={formData.senderAddress.postCode}/>
<label>Country</label>
<input {...register("senderAddress.country")} defaultValue={formData.senderAddress.country}/>
<label>Client"s Name</label>
<input {...register("clientName")} defaultValue={formData.clientName}/>
<label>Client"s Email</label>
<input {...register("clientEmail")} defaultValue={formData.clientEmail}/>
<label>Street Address</label>
<input {...register("clientAddress.street")} defaultValue={formData.clientAddress.street}/>
<label>City</label>
<input {...register("clientAddress.city")} defaultValue={formData.clientAddress.city}/>
<label>Postal Code</label>
<input {...register("clientAddress.postCode")} defaultValue={formData.clientAddress.postCode}/>
<label>Country</label>
<input {...register("clientAddress.country")} defaultValue={formData.clientAddress.country}/>
<label>Invoice Date</label>
<input {...register("createdAt")} defaultValue={formData.createdAt}/>
<label>Payment Terms</label>
<input {...register("paymentTerms")} defaultValue={formData.paymentTerms}/>
<label>Project Description</label>
<input {...register("description")} defaultValue={formData.description}/>
{/* //Item list goes here */}
<input type="submit" placeholder="Submit"/>
</form>
<button onClick={closeModal}>Close</button>
</ReactModal>
</>
)
}
It may be sloppy code as of now and was working to clean it up a lot more until I noticed this issue.
In your parent, try adding a placeholder.
<div id="react-modals" />
Your react modal seems to be looking for a div with the #react-modals id.
I am trying to set up some functionality on this React component so that a user can add and remove empty radio button options to a page that a user can type text into. The only issue that I am having is that I am relatively new to React and am not 100% how to do this.
import React, { Component } from 'react';
class TextRadio extends Component {
constructor() {
super();
state = {
textValue: ""
}
};
handleInputChange = event => {
const value = event.target.value;
const name = event.target.name;
this.setState({
[name]: value
});
}
addBox = () => {
}
removeBox = () => {
}
render() {
return(
<div>
<div className="form-check">
<input className="form-check-input" type="radio" id="" name="" value="" />
<label className="form-check-label" for="">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button type="button" className="btn btn-danger" onClick={this.removeBox}>
Remove Option
</button>
</div>
);
}
}
export default TextRadio;
The result that I am expecting to happen is to have it so the component can add and remove radio button options from the page depending on the button that the user presses
i was completed just your addBox and RemoveBox functions, i hope that's help you
import React, { Component } from "react";
class TextRadio extends Component {
constructor() {
super();
this.state = {
radioButtons: []
};
}
handleInputChange = event => {
const value = event.target.value;
const name = event.target.name;
};
addBox = () => {
this.setState(prevstate => {
let radioButtons = prevstate.radioButtons;
if (radioButtons.length === 0) {
radioButtons.push({
id: 1,
name: "radiobutton",
value: "test"
});
return {
radioButtons: radioButtons
};
} else {
radioButtons.push({
id: radioButtons[radioButtons.length - 1].id + 1,
name: "raiodButton_" + (radioButtons[radioButtons.length - 1].id + 1),
value: radioButtons[radioButtons.length - 1].value
});
return {
radioButtons: radioButtons
};
}
});
};
removeBox = () => {
this.setState(prevstate => {
let radioButtons = prevstate.radioButtons;
if (radioButtons.length !== 0) {
radioButtons.pop(radioButtons[radioButtons.length - 1]);
return {
radioButtons: radioButtons
};
} else {
return { radioButtons: radioButtons };
}
});
};
render() {
return (
<div>
<div className="form-check">
{this.state.radioButtons.map(radiobutton => {
return (
<div>
<input
className="form-check-input"
type="radio"
id={radiobutton.id}
name={radiobutton.name}
value={radiobutton.value}
/>
<label className="form-check-label" for="">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
);
})}
</div>
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button
type="button"
className="btn btn-danger"
onClick={this.removeBox}
>
Remove Option
</button>
</div>
);
}
}
export default TextRadio;
https://codesandbox.io/embed/confident-browser-tmojp
I was playing around with your idea and made some changes in the code, just to show you an example, how you can dynamically create new components and store them in applications state and then render out to user based on their actions.
I created new component just for form UI: option, input field and remove button. If user clicks on the Add Option, new item of the component is added to application state and then render out. Remove button is used to remove Item from state.
class TextRadio extends Component {
state = {
optionInputs: []
};
addBox = () => {
const optionInputsUpdated = [
...this.state.optionInputs,
<OptionInput id={uuid.v4()} remove={this.removeBox} />
];
this.setState({ optionInputs: optionInputsUpdated });
};
removeBox = id => {
const optionInputsUpdated = this.state.optionInputs.filter(
item => item.props.id !== id
);
this.setState({ optionInputs: optionInputsUpdated });
};
render() {
return (
<div>
{this.state.optionInputs.map((optionInput, idx) => {
return (
<div key={idx} test="123">
{optionInput}
</div>
);
})}
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
</div>
);
}
}
const OptionInput = props => {
return (
<div className="form-check">
<input
className="form-check-input"
type="radio"
id=""
name="radio"
value=""
/>
<label className="form-check-label" for="">
<input className="form-control" type="text" placeholder="" />
</label>{" "}
<button
type="button"
className="btn btn-danger"
onClick={() => props.remove(props.id)}
>
Remove Option
</button>
</div>
);
};
Hope this gives you better understanding, how to achieve your goal.
If you need additional help, just post a comment under this answer, and I will update demo to help you.
Here is DEMO I created from your code: https://codesandbox.io/s/nice-ganguly-s4wls
first you have to initialize an empty array state
this.state={
radioButtons : [{input:''}]
}
then in your return statement you have to loop through the radioButtons array and show the radio button with input
{
this.state.radioButtons.map(item => (
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
))
}
then in your addBox function append an object on every click
addBox = () => {
this.setState({radioButtons:[...this.state.radioButtons, {input:''}]})
}
function to remove a radio button object
removeBox = () => {
let radioArray = this.state.radioButtons
radioArray.pop()
this.setState({radioButtons:radioArray})
}
Final code Looks like this :
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component{
constructor(props){
super(props);
this.state={
radioButtons :[{input:''}]
}
}
addBox = () => {
this.setState({radioButtons:[...this.state.radioButtons, {input:''}]})
}
removeBox = () => {
let radioArray = this.state.radioButtons
radioArray.pop()
this.setState({radioButtons:radioArray})
}
render(){
return(
<div>
{
this.state.radioButtons.map(item => (
<div className="form-check">
<input className="form-check-input" type="radio" id="option" name="option" value="option" />
<label className="form-check-label" for="option">
<input class="form-control" type="text" placeholder="" />
</label>
</div>
))
}
<button type="button" className="btn btn-primary" onClick={this.addBox}>
Add Option
</button>
<button type="button" className="btn btn-danger" onClick={this.removeBox}>
Remove Option
</button>
</div>
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
codepen Example
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>
);
}
}