Conditional rendering inputs overlap text - javascript

I've been trying to make a form where, depending on a switch button, renders one or two different inputs.
My code looks like this:
const Test = () => {
const [switchButton, setSwitch] = React.useState(true)
const handleSwitch = () => {setstate(!switchButton)}
return <>
<Switch checked={switchButton} onClick={() => handleSwitch} />
{!switchButton ?
<>
<label htmlFor="input_1">Input 1</label>
<input id="input_1"/>
</>
:
<>
<label htmlFor="input_2">Input 2</label>
<input id="input_2" />
<label htmlFor="input_3">Input 3</label>
<input id="input_3" />
</>
}
</>
}
export default Test;
My issue happens when I enter characters into one input and then switch them: The same characters are shown on my new rendered input. Example here.
Why does this happen? I'm really lost

use keys for the elements, so it will not be recognized as the same element as react tries to map elements on each rerender if they were already rendered before.
so react sees: 1 input and than 2 inputs and thinks the first input is the same as before.
const Test = () => {
const [switchButton, setSwitch] = React.useState(true)
const handleSwitch = () => setSwitch((switch) => !switch)
return (
<>
<Switch checked={switch} onClick={handleSwitch} />
{!switchButton ? (
<React.Fragment key="key1">
<label htmlFor="input_1">Input 1</label>
<input id="input_1"/>
</>
) : (
<React.Fragment key="key2">
<label htmlFor="input_2">Input 2</label>
<input id="input_2" />
<label htmlFor="input_3">Input 3</label>
<input id="input_3" />
</>
)}
</>
)}
export default Test;
but anyway it would be better to use a controlled input. something like this:
const [value, setValue] = React.useState(true)
<input value={value} onChange={(e) => setValue(e.target.value)}/>

Related

Set filter value conditionally using radio button and input search in react table

export const DefaultColumnFilter11 = ({
column: {
filterValue,
setFilter,
preFilteredRows: { length },
},
}) => {
const [condVal, setcondVal] = useState("");
return (
<div>
<input
type="radio"
value=">"
name="cond"
onChange={(event) => setcondVal(event.target.value)}
/>{" "}
<
<br />
<input
type="radio"
value="<"
name="cond"
onChange={(event) => setcondVal(event.target.value)}
/>
>
<br />
<Input
value={filterValue|| ""}
onChange={(e) => {
setFilter( {condVal} && (e.target.value || undefined));
}}
placeholder={`${length}`}
/>
</div>
);
};
This is the code and I want to filter the column using radio button condition greater than ">" and less than "<" that should be applied to the input search.
Essentially I have some data that I would like to filter using radio buttons.
Selecting a button of a particular value should only cause those objects with that value as their property to be rendered.

Disabled button based on React input fields not working properly

So I'm trying to enable a button, after two fields have been selected, but for some reason, I have to click on the second field twice to trigger it to enabled. Can anyone see what I'm doing wrong?
So to confirm, when I click on a price and when I click on donateTo field, it is setting state correctly, however it doesn't enable the bottom at the bottom until I have clicked one of the fields a third or fourth time.
const DonateBox = ({ goToPayment }) => {
const [price, setPrice] = useState('');
const [donateTo, setDonateTo] = useState('');
const [isProgressDisabled, setDisabled] = useState(true);
const handleSetDonateTo = (e) => {
setDonateTo(e.target.value);
disabledCheck();
};
const handlePriceClick = (e) => {
setPrice(e.target.value);
disabledCheck();
};
const handleGoToPayment = () => {
goToPayment('paymentbox');
};
const disabledCheck = () => {
if (price && donateTo) {
setDisabled(false);
}
console.log(isProgressDisabled);
};
return (
<>
<div className={styles.donateBox}>
<p className={styles.heading}>
Give through the most effective platform for good.
</p>
<p className={styles.subheading}>
100% goes to the causes listed in the article here. You are one click
away!
</p>
<div className={styles.itemList}>
<label className={styles.labelWrapper}>
<input
type="radio"
className={styles.customRadio}
value="cause"
onClick={handleSetDonateTo}
checked={donateTo === 'cause'}
/>
<span>Donate to Cause</span>
</label>
<label className={styles.labelWrapper}>
<input
type="radio"
className={styles.customRadio}
value="charity"
onClick={handleSetDonateTo}
checked={donateTo === 'charity'}
/>
<span>Donate to Charity</span>
</label>
<label className={styles.labelWrapper}>
<input
type="radio"
className={styles.customRadio}
value="goods"
onClick={handleSetDonateTo}
checked={donateTo === 'goods'}
/>
<span>Donate to Goods</span>
</label>
</div>
<div className={styles.priceList}>
<label
className={`${styles.priceLabel} ${
price === '25' ? `${styles.selected}` : ''
}`}
>
<input
type="radio"
name="25"
className={styles.priceInput}
onClick={handlePriceClick}
value="25"
/>
$25
</label>
<label
className={`${styles.priceLabel} ${
price === '50' ? `${styles.selected}` : ''
}`}
>
<input
type="radio"
name="50"
className={styles.priceInput}
onClick={handlePriceClick}
value="50"
/>
$50
</label>
<label
className={`${styles.priceLabel} ${
price === '75' ? `${styles.selected}` : ''
}`}
>
<input
type="radio"
name="75"
className={styles.priceInput}
onClick={handlePriceClick}
value="75"
/>
$75
</label>
</div>
</div>
<button
className={styles.largeButton}
onClick={handleGoToPayment}
disabled={isProgressDisabled}
>
Add Card Details
</button>
</>
);
};
export default DonateBox;
In addition to #adesurirey's suggestion, this is the perfect scenario for useEffect.
When the variable(s) inside of the dependency array are changed, the code in useEffect is invoked.
Meaning, you can automatically invoke the disabledCheck if price or donateTo are changed. This way you don't have to remember to call disabledCheck within the handlers.
Edit another excellent thing about useEffect in a scenario like this is that you know for sure disabledCheck is invoked only after state is changed. Since mutating state is async, it is possible that disabledCheck was running before state was actually updated.
Think of useEffect like the callback function within setState (on class based components)..
// Class based comparison...
// You know for sure `disabledCheck` is only called *after*
// state has been updated
setState({
some: 'newState'
}, () => disabledCheck());
Demo:
const { useState, useEffect, Fragment } = React;
const { render } = ReactDOM;
const DonateBox = ({ goToPayment }) => {
const [price, setPrice] = useState('');
const [donateTo, setDonateTo] = useState('');
const [isProgressDisabled, setDisabled] = useState(true);
const handleSetDonateTo = (e) => {
setDonateTo(e.target.value);
// disabledCheck();
};
const handlePriceClick = (e) => {
setPrice(e.target.value);
// disabledCheck();
};
const handleGoToPayment = () => {
goToPayment('paymentbox');
};
const disabledCheck = () => {
if (price !== '' && donateTo !== '') {
setDisabled(false);
}
console.log(isProgressDisabled);
};
useEffect(() => {
disabledCheck();
}, [price, donateTo]);
return (
<Fragment>
<div>
<p>
Give through the most effective platform for good.
</p>
<p>
100% goes to the causes listed in the article here. You are one click
away!
</p>
<div>
<label>
<input
type="radio"
value="cause"
onClick={handleSetDonateTo}
checked={donateTo === 'cause'}
/>
<span>Donate to Cause</span>
</label>
<label>
<input
type="radio"
value="charity"
onClick={handleSetDonateTo}
checked={donateTo === 'charity'}
/>
<span>Donate to Charity</span>
</label>
<label>
<input
type="radio"
value="goods"
onClick={handleSetDonateTo}
checked={donateTo === 'goods'}
/>
<span>Donate to Goods</span>
</label>
</div>
<div>
<label>
<input
type="radio"
name="25"
onClick={handlePriceClick}
value="25"
/>
$25
</label>
<label>
<input
type="radio"
name="50"
onClick={handlePriceClick}
value="50"
/>
$50
</label>
<label>
<input
type="radio"
name="75"
onClick={handlePriceClick}
value="75"
/>
$75
</label>
</div>
</div>
<button
onClick={handleGoToPayment}
disabled={isProgressDisabled}
>
Add Card Details
</button>
</Fragment>
);
};
const App = () => <DonateBox />
render(<App />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
You should use onChange events on your inputs instead of onClick
<input
type="radio"
name="75"
className={styles.priceInput}
onChange={handlePriceClick}
value="75"
/>

Setting default checked radio button using Redux Form

I'm trying to set a radio button to default checked using the following:
import { Field } from "redux-form";
<Field name={radio_name} component={renderField} type="radio" checked={true} value={val1} label="val1"/>
<Field name={radio_name} component={renderField} type="radio" value={val2} label="val2"/>
<Field name={radio_name} component={renderField} type="radio" value={val3} label="val3"/>
const renderField = ({
input,
label,
type
}) =>
(
<div>
<input {...input} type={type}/>
<label>{label}</label>
</div>
);
However, there's no checked property in the resulting element. Anyone know why?
You didn't use the checked prop:
const renderField = ({ input, label, type, checked }) => (
<div>
<input {...input} type={type} checked={checked} />
<label>{label}</label>
</div>
);

Cannot read property 'map' of undefined - Error from ReactJS

Error Message:
Error: Cannot read property 'map' of undefined
React component:
const checkBox = props => {
return (
<div>
<label htmlFor={props.name} className='form-label'>
{props.title}
</label>
<div className='checkbox-group'>
{
props.options.map(option => {
return (
<label key={option}>
<input
className='form-checkbox'
id={props.name}
name={props.name}
onChange={props.handleChange}
value={option}
checked={props.selectedOptions.indexOf(option) > -1}
type='checkbox'
/>{' '}
{option}
</label>
)
})
}
</div>
</div>
)
}
In my code is anything going wrong? If yes please let me know. Can someone help me out from this?
The error
Cannot read property 'map' of undefined
Is thrown when the map function in the comment list component is executed.
A question comment references a tutorial showing how to build a form and its sub-components. A couple of the components include examples of how to pass props, but that's missing from <Checkbox/>.
To fill that gap, here's an example of how you might expect to use <Checkbox/>. I didn't read the article in its entirety, so I'm hoping you can help correct any mistakes I've made here and it gets you started on your own development.
<Checkbox
title={'Skills'}
name={'skills'}
options = {this.state.skills} <!-- array of skills or empty array -->
selectedOptions = {this.state.newUser.skills} <!-- array of skills or empty array -->
handleChange = {this.handleInput}
/>
You could also use a simple fallback like.
const checkBox = props => {
const { options, name, titlem, selectedOptions, handleChange } = props
return (
<div>
<label for={name} className="form-label">
{title}
</label>
<div className="checkbox-group">
{(options || []).map(option => {
return (
<label key={option}>
<input
className="form-checkbox"
id={name}
name={name}
onChange={handleChange}
value={option}
checked={selectedOptions.indexOf(option) > -1}
type="checkbox"
/>{" "}
{option}
</label>
);
})}
</div>
</div>
);
};
const checkBox = ({ options, name, title, selectedOptions, handleChange }) => {
return (
<div>
<label htmlFor={name} className='form-label'>
{title}
</label>
<div className='checkbox-group'>
{
options && options.map(option => {
return (
<label key={option}>
<input
className='form-checkbox'
id={name}
name={name}
onChange={handleChange}
value={option}
checked={selectedOptions.indexOf(option) > -1}
type='checkbox'
/>{' '}
{option}
</label>
)
})
}
</div>
</div>
)
}

Input Text validation in react for containing at least one character and one number

i want to add a validation in an input field when user enters a value onKeyDown event. The validation is that my input must contain at least on Character and a least one number. The validation texts must be enabled or disabled when the validations are true. Also if the user backspaced and the text is not containg at least one value or one number the validations must be enabled. I've set the internal state with two flag. My question is how my validation function must be?
Code:
const InputField = props => (
<div className="input-row">
<input
{...props.input}
type={props.type}
className="form-control input-box__input"
placeholder={props.placeholder}
value={props.value}
defaultValue={props.defaultValue}
defaultChecked={props.defaultChecked}
disabled={props.disabled}
onChange={props.onChange}
onKeyDown={this.onKeyDown}
checked={props.checked}
/>
{props.meta.touched && props.meta.error &&
<span className="error">
{props.intl.formatMessage({ id: props.meta.error }) }
</span>}
</div>
);
const onKeyDown = (e) => {
// Add logic here
}
}
please check the following link
https://jsfiddle.net/69z2wepo/201010/
it has the following code:
class Hello extends React.Component {
state = {hasError:false};
onChange(event){
if(event.target.value.match(/^(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)$/)){
this.setState({hasError:false});
}else{
this.setState({hasError:true});
}
}
render() {
return <div>
<input name="name" onChange={this.onChange.bind(this)}/>
{this.state.hasError && <span>Error</span>}
</div>;
}
}
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
this works as you expect it to in a react application.
btw
1) You can replace
<input
{...props.input}
type={props.type}
className="form-control input-box__input"
placeholder={props.placeholder}
value={props.value}
defaultValue={props.defaultValue}
defaultChecked={props.defaultChecked}
disabled={props.disabled}
onChange={props.onChange}
onKeyDown={this.onKeyDown}
checked={props.checked}
/>
With
<input
{...props.input}
{...props}
className="form-control input-box__input"
onKeyDown={this.onKeyDown}
/>
2) You can use html power ( https://www.w3schools.com/html/tryit.asp?filename=tryhtml5_input_pattern ) and do next:
<input
{...props.input}
{...props}
{...this}
/>
Where properties of this class are
className = 'form-control input-box__input';
onChange = (e) => {
e.target.checkValidity();
if (this.props.onChange) this.props.onChange()
}
But to use it, input must be inside <form></form>

Categories