I'm new to react and redux and i want to create component which contain two radio buttons so i write something like this:
import React, { PropTypes } from 'react';
const renderCashRadioButtons = currentCashSelector => (
<form onClick={currentCashSelector}>
<input
type="radio"
name="cash-transaction"
value="Transcation"
onChange={value => currentCashSelector(value)}
/>
<input
type="radio"
name="cash-transfer"
value="Transfer"
onChange={value => currentCashSelector(value)}
/>
</form>
);
const CashRadioButtons = ({ currentCashSelector }) => (
<div className="container">
{renderCashRadioButtons(currentCashSelector)}
</div>
);
CashRadioButtons.propTypes = {
currentCashSelector: PropTypes.func.isRequired
};
export default CashRadioButtons;
currentCashSelector is a function. When i render this it does not seem to work. The value does not change and i'm not seeing the state to be updated. Do you have any ideas?
You probably want your radio buttons to have the same name, so that when one is selected, the other is deselected.
It looks like your onChange functions are expecting the value, but they're actually receiving the event.
You likely have unwanted duplication between the onChange on your form, and the ones on your radio buttons.
Possible Solution
<form onClick={event => currentCashSelector(event.target.value)}>
<input
type="radio"
name="cash-type"
value="Transaction"
/>
<input
type="radio"
name="cash-type"
value="Transfer"
/>
</form>
Related
I am new to react and I got a scenario where I have multiple checkboxes on my form. I want the user to check all the checkboxes only then enable the submit button on the form. On Load, the submit button will be disabled. How to do this?
Here is the code that I have written so far:
const MultipleCheckboxes = () => {
const handleChange = () => {
}
const allChecked = () => {
}
return (
<div>
<form>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value="Java"
id="languageChkDefault"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Javascript
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value="Angular"
id="languageChkDefault"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Angular
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value="Python"
id="languageChkDefault"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Python
</label>
</div> <br />
<button disabled={!allChecked}>Submit</button>
</form>
</div>
);
};
export default MultipleCheckboxes;
Can anybody help me on this? thank you
This is my solution, I hope it helps you
import { useState, useEffect } from "react";
const MultipleCheckboxes = () => {
const [allChecked, setAllChecked] = useState(false);
const [checkboxes, setCheckboxes] = useState({
javaCheckbox: false,
angularCheckbox: false,
pythonCheckbox: false
});
function handleChange(e) {
setCheckboxes({
...checkboxes,
[e.target.id]: e.target.checked
})
}
useEffect(() => {
const result = Object.values(checkboxes).every(v => v);
console.log(result);
setAllChecked(result);
}, [checkboxes]);
return (
<div>
<form>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value={checkboxes.javaCheckbox}
id="javaCheckbox"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Javascript
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value={checkboxes.angularCheckbox}
id="angularCheckbox"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Angular
</label>
</div>
<div className="form-check">
<input
type="checkbox"
className="some-class-name-chk"
name="someName"
value={checkboxes.pythonCheckbox}
id="pythonCheckbox"
onChange={handleChange}
/>
<label
className="form-check-label"
htmlFor="languageChkDefault"
>
Python
</label>
</div> <br />
<button disabled={!allChecked}>Submit</button>
</form>
</div>
);
};
export default MultipleCheckboxes;
You can use react useState hook and set its default value to false.
const [state, setstate] = useState(false)
When the user clicks on an input box set the state to true. You may encounter some problems when the user unchecks the box, so you can use an if statement to handle state change
For example:
if (state === true){
setstate(false)
}else{
setstate(true)
}
or you can just use this code inside the handleChange function:
!state
It inverses the state to true/false accordingly.
After that you can use a ternary operator inside the component to check whether the user has checked all the boxes, if the user hasn't checked all the boxes, disable the button or else do otherwise.
For example, if the state is true (or in other words, if the user has checked the box), render the normal styled button, else render the disabled button:
{state? <button className = "styled"/>: <button disabled className="styled"/>}
Of course, I have only checked the state of one input box. Now you can simply check for multiple conditions by declaring multiple states for each box.
{state1 && state2 && state3 ? <button className = "styled"/>: <button disabled className="styled"/>}
If you are not yet familiar with ternary operators, you should go through this doc Ternary operators.
If you haven't heard of useState and react hooks yet, feel free to look the React's documentation. Welcome to the React ecosystem!
I am working on some code that takes the inputs from two textboxes, one that takes a string value and one that takes a number value, and in real time writes it to a paragraph without a submit button. I am having trouble finding any information on this process without submitting anything. The paragraph should just display . To begin, this is what I have:
import './App.css';
function App() {
return (
<div>
<form>
<div>String:</div>
<input type="text" strng = "strng" /><br/><br/>
<div>Number:</div>
<input type="text" strng = "number"/><br/><br/>
<button>Clear</button>
<p>
Inputs:
</p>
</form>
</div>
)
}
export default App;
Would someone be able to help me out with writing the two text boxes to the paragraph in real time? Thanks so much in advance.
You should be able to bind a useState with the onChange event of the input
import './App.css';
import { useState } from "react";
function App() {
const [text, setText] = useState("");
return (
<div>
<form>
<div>String:</div>
<input
type="text"
strng="strng"
onChange={(e) => setText(e.target.value)}
/>
<br />
<br />
<div>Number:</div>
<input type="text" strng="number" />
<br />
<br />
<button>Clear</button>
<p>Input: {text}</p>
</form>
</div>
);
}
I am trying to get useFormik to validate radio groups, but it seems not to work, here is a brief example of what I am doing, whenever I submit the form after checking any of the radio input, formik throws validation error, ({currState:"you must choose property state"}), even though I choose an option.
I realized getFieldProps attaches value field to the radio, so i tried using defaultValue then react throws an error about choosing one of controlled and uncontrolled components.
import { useFormik } from "formik"
export function ListProperty(){
const { handleSubmit, getFieldProps, touched, errors } = useFormik(
{
initialValues: {
currState:"",
},
validationSchema:Yup.object().shape({
currState:Yup.string().required("you must choose property state")
}),
return (
<form onSubmit={handleSubmit} >
<div className="form-group inline">
<div className="form-control">
<input type="radio"
name="currState"
{...getFieldProps("currState")}
value="serviced"
/>
<label>serviced</label>
</div>
<div className="form-control">
<input
type="radio"
value="furnished"
name="currState"
{...getFieldProps("currState")}
/>
<label>furnished</label>
</div>
<div className="form-control">
<input
type="radio"
value="newlybuilt"
name="currState"
{...getFieldProps("currState")}
/>
<label>newly built</label>
</div>
</div>
<button type="submit">submit </button>
</form>
)
}
I gave up on the implementation with getFieldProps and did it simpler, like this:
import { useFormik } from 'formik'
export default function Component() {
const formik = useFormik({
initialValues: {
radioButtonValue: ''
},
onSubmit: values => console.log(values)
})
const handleRadioButtons = e => formik.values.radioButtonValue = e.target.value
return (
<form onSubmit={formik.handleSubmit}>
<input
type="radio"
id="one"
name="group"
value="One"
onChange={e => handleRadioButtons(e)}
required
/>
<label htmlFor="one">One</label>
<br />
<input
type="radio"
id="two"
name="group"
value="Two"
onChange={e => handleRadioButtons(e)}
/>
<label htmlFor="two">Two</label>
<button type="submit">Submit</button>
</form>
)
}
Beware, if you use formik.values.radioButtonValue value as a useEffect dependency, then setting it like this: formik.values.radioButtonValue = e.target.value not gonna trigger the change, and useEffect won't launch (at least in my case it didn't). As an alternative, you gonna have to implement some kind of condition check with this value in your useEffect code
You need to map onChange like below.
<input
type="radio"
value="furnished"
name="currState"
onChange={getFieldProps("currState").onChange}
/>
I have a radio button using pure css, but it doesn't work on first click, it only work on the second click onward, not sure it has to do with my react prop or not:
const Radio = ({ id, name, value, checked, children }) => (
<div className="radioBtn">
<input type="radio" value={value} id={id} name={name} checked={checked} />
<label className={"radio"} htmlFor={id}>
<span className={"big"}>
<span className={"small"} />
</span>
<span>{children}</span>
</label>
</div>
);
https://codesandbox.io/s/react-sass-34b8w
Use defaultChecked instead of checked={checked}.
I want to upload and read a file locally, but I want to do that using a custom button not using HTML input.
<input type="file" id="my_file_input" />
I found this way but I don't want to use this shape or this button, I wanted to use a material UI Raised Button to do this functionality to match the other site Button.
I also tried the following way but it didn't work because as i clicked the button nothing happened.
<input type="file" id="my_file_input" style={{display:"none"}}/>
<label htmlFor="my_file_input">
<RaisedButton
label="Import from Excel"
labelColor="#FFFFFF"
backgroundColor="#01579b"
/>
</label>
I thought I should do the uploading/reading file functionality manually in the onClick function of the RaisedButton but I didn't find a way to do that.
So is there any other solution for this problem in react?
I hope this code will help you.
We can solve it in two ways.
1-)
HTML
<div>
<input type="file" hidden ref={this.inputReference} onChange={this.fileUploadInputChange} />
<button className="ui button" onClick={this.fileUploadAction}>
Image Upload
</button>
{this.state.fileUploadState}
</div>
REACT CONSTRUCTOR
constructor(props) {
super(props);
this.state={fileUploadState:""}
this.inputReference = React.createRef();
}
ONCLICK FUNCTION
fileUploadAction = () =>this.inputReference.current.click();
fileUploadInputChange = (e) =>this.setState({fileUploadState:e.target.value});
2-)
HTML
<div>
<input id="fileButton" type="file" hidden />
<button onClick={this.fileUploadButton}>
Image Upload
</button>
{this.state.fileUploadState}
</div>
React State
this.state = {fileUploadState:""}
React Function
fileUploadButton = () => {
document.getElementById('fileButton').click();
document.getElementById('fileButton').onchange = () =>{
this.setState({
fileUploadState:document.getElementById('fileButton').value
});
}
}
I wanted to provide an update for using refs with functional components. Here is a quick example:
Import React, {useRef} from 'React'
const myComponent = () => {
const fileInputRef=useRef();
const handleChange(event) = () =>{
// do something with event data
}
return(
<>
<button onClick={()=>fileInputRef.current.click()}>
Custom File Input Button
</button>
<input onChange={handleChange} multiple={false} ref={fileInputRef} type='file'hidden/>
</>
)
}
please read API of React Material https://material-ui.com/demos/buttons/
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
const styles = theme => ({
button: {
margin: theme.spacing.unit,
},
input: {
display: 'none',
},
});
function ContainedButtons(props) {
const { classes } = props;
return (
<div>
<input
accept="image/*"
className={classes.input}
id="contained-button-file"
multiple
type="file"
/>
<label htmlFor="contained-button-file">
<Button variant="raised" component="span" className={classes.button}>
Upload
</Button>
</label>
</div>
);
}
ContainedButtons.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ContainedButtons);
As the doc says, you just need to add:
component="span"
To the button component.