React-select: isClearable does not work if onChange is used - onchange

Instead of clearing the options, the dropdown toggles when clicking on the X icon from isClearable. If I don't have an onChange prop, it clears.

use
onChange={(value) => { setFilterParams({ ...filterParams, group: value })}
not
onChange={(value) => {setFilterParams({ ...filterParams, group: value.id })}

Related

Updating nested state in React Native when mapping over data

I am mapping over state which displays 3 radio buttons and I only want 1 out of the 3 to be selected at one time and show the selected radio button style - so just a standard behaviour.
The first radio button - isChecked is defaulted to true and I then want to be able to switch the selected styles onPress of the other radio buttons which displays an inner filled circle.
I am getting confused on how to handle the isChecked as true for only the selected Radio Button onPress. I believe I should be using the index of the map to update the state but im unsure on how to go about it.
const [option, setOption] = useState([
{ permission: 'Standard User', isChecked: true },
{ permission: 'Approver', isChecked: false },
{ permission: 'Administrator', isChecked: false },
]);
const RadioButton = ({ checked, onCheck }) => (
<StyledRadioButton onPress={onCheck}>
{checked && <SelectedRadioButton />}
</StyledRadioButton>
);
{option.map(({ isChecked }, i) => (
<RadioButton
onCheck={() =>
setOption(
...prev => {
!prev.isChecked;
},
)
}
checked={isChecked}
/>
))}
Your state is an array of objects which hold a boolean flag. If the user checks a checkbox, then this flag should be set to true while all the others should be set to false. The setter of the state receives an array again, thus we could use the map function again as well as the index argument as you have suggested yourself in your question.
{option.map(({ isChecked }, i) => (
<RadioButton
onCheck={() =>
setOption(
prev => prev.map((opt, index) => ({...opt, isChecked: i === index ? true : false}))
)
}
checked={isChecked}
/>
))}

How can I use react-native-dropdown-picker(DropDownPicker) without open, setOpen properties?

const [openDropdown, setOpenDropdown] = useState(false);
<Controller
control={control}
name={EPaymentFormField.PROMOTION_COUPON_ID}
render={({ field: { value, onChange } }) => {
const handleChange = (callback: any) => {
onChange(callback());
};
return (
<DropdownPicker
placeholder={t('paymentDetail_coupon_label', {
numOfAvailableCoupons: numOfAvailableCoupons,
numOfTotalCoupons: numOfTotalCoupons,
})}
open={openDropdown}
setOpen={setOpenDropdown}
value={value}
setValue={handleChange}
items={dropdownData}
multiple={false}
/>
);
}}
/>
How can I use without open, setOpen properties on DropDownPicker?
these are essential properties in this library.
But I don't want to use useState.
So, If it can, I want to use it without open, setOpen properties or useState.
Is anyone knows solution?
I don't think the lib forces you to use useState
You should be able to pass a boolean is and a random function to like so :
<DropdownPicker
placeholder={t('paymentDetail_coupon_label', {
numOfAvailableCoupons: numOfAvailableCoupons,
numOfTotalCoupons: numOfTotalCoupons,
})}
open={true} // if you want to keep it open
setOpen={() => return;}
value={value}
setValue={handleChange}
items={dropdownData}
multiple={false}
/>

React-Native Switch uncontrolled using an object doesn't change value

I have a react-native project in which I'm trying to handle the Switch component in a way that I can dynamically set an object with the boolean and its value, but I doesn't respond well:
Initially I use useEffect to process the data:
useEffect(() => {
let lista = {}
Object.entries(planes).forEach(([j, plan]) => {
lista[plan.nombre] = false
})
setSeleccion(lista)
}, []);
Then I loop through my data to load it and create the "card" dynamically with a Switch:
<Switch
offTrackColor="indigo.100"
onTrackColor="indigo.300"
onThumbColor="coolgray.500"
offThumbColor="indigo.50"
size="lg"
onToggle={(val) => toggleSwitch(val, plan.nombre)}
value={seleccion[plan.nombre]}
/>
Then toggle function:
const toggleSwitch = (val, plan) => {
setSeleccion({...seleccion, [plan]: val})
};
Now if I print the new array it shows as expected:
useEffect(() => {
console.log(seleccion)
}, [seleccion]);
But sadly the Switch remains as false visually (just goes back to its false state, so one cant toggle back to off/false).
If I do a toString(seleccion[plan.nombre]) in the render it shows [object Undefined]
Assuming that the Switch that you used is same/from react-native. There shouldn't be a prop called onToggle in Switch like you wrote below.
<Switch
offTrackColor="indigo.100"
onTrackColor="indigo.300"
onThumbColor="coolgray.500"
offThumbColor="indigo.50"
size="lg"
onToggle={(val) => toggleSwitch(val, plan.nombre)}
value={seleccion[plan.nombre]}
/>
instead, you need to use onValueChange
<Switch
offTrackColor="indigo.100"
onTrackColor="indigo.300"
onThumbColor="coolgray.500"
offThumbColor="indigo.50"
size="lg"
onValueChange={(val) => toggleSwitch(val, plan.nombre)}
value={seleccion[plan.nombre]}
/>
You can read more about the props in Switch here

Implementing react-hook-forms and react-select with radio buttons and multi inputs combo

Ready for a complicated one?
Using react-hook-forms and react-select using creatable (user creates multiple inputs on the fly)
I'm trying to implement a form that uses an option on 4 radio buttons, 2 of which reveal multi inputs (inputs that use react-select where the user can create multiple entries, not a dropdown) and trying to keep track of both the radio inputs and the multi inputs in the final useForm() object. I also need to be able to remove them if the user changes their mind or resets the form in total. Right now, the key values of registrationTypes changes when I change radioTwo and enter inputs. I also don't know how to remove user inputs. I'm using Controller to read the entries (although I've heard if you're using native HTML checkbox input, you have to use Register?) . Here's the code:
import styled from 'styled-components'
import Creatable from 'react-select/creatable'
import { Controller } from 'react-hook-form'
import { ErrorRow } from '../util/FormStyles'
import { FormRulesProps } from '../util/formRuleTypes'
import FormError from './FormError'
const registrationTypes = [
{
label: 'Allow anyone with the link to register',
value: 'radioOne',
},
{
label: 'Allow anyone with this email domain to register:',
value: 'radioTwo',
},
{ label: 'Allow anyone with this code to register:', value: 'radioThree' },
{
label: 'Define eligible users manually through eligibilty file.',
value: 'radioFour',
},
]
const RegistrationEligibilty = () => {
const {
control,
reset,
handleSubmit,
formState: { errors },
} = useForm<any>()
const [selectedRadio, setSelectedRadio] = useState({ regType: '' })
const onSubmit = (data: any) => {
console.log(data)
}
const handleSelected = (value: string) => {
setSelectedRadio({ ...selectedRadio, regType: value })
}
return (
<RegistrationEligibiltyContainer>
<form onSubmit={handleSubmit(onSubmit)}>
<FormRow>
<RadioWrapper>
{registrationTypes.map((rt) => (
<Controller
key={rt.value}
control={control}
name="radio"
render={({ field: { onChange, value } }: any) => (
<RadioGroup
// #ts-ignore
value={value}
onChange={(e: any) =>
onChange(e.target.value, handleSelected(rt.value))
}
>
<Radio
name={rt.value}
type="radio"
value={rt.value}
checked={selectedRadio.regType === rt.value}
/>
<TextRow
text={rt.label}
style={{ paddingLeft: '10px' }}
/>
{selectedRadio.regType === 'radioTwo' &&
rt.value === 'radioTwo' && (
<FormRow>
<div style={{ width: '90%' }}>
<Controller
name={rt.value}
control={control}
render={({ field }) => (
<Creatable
{...field}
isMulti
options={field.value}
value={field.value}
placeholder="Select domains"
/>
)}
/>
</div>
</FormRow>
)}
{selectedRadio.regType === 'radioThree' &&
rt.value === 'radioThree' && (
<FormRow>
<div style={{ width: '90%' }}>
<Controller
name={rt.value}
control={control}
render={({ field }) => (
<Creatable
{...field}
isMulti
options={field.value}
value={field.value}
placeholder="Select codes"
/>
)}
/>
</div>
</FormRow>
)}
</RadioGroup>
)}
/>
))}
</RadioWrapper>
</FormRow>
</FormContent>
</form>
</RegistrationEligibiltyContainer>
)
}
export default RegistrationEligibilty
The result looks like this:
https://imgur.com/a/6oGhqRb
I also need to be able to remove them if the user changes their mind or resets the form in total
If the component is unmounted, the value of the component is not included in the result. Make sure your Creatable is unmounted when the relevant radio is not selected

How to set state on child component?

I have a component that renders out a list of buttons, lets call this 'ButtonList'. When one of the buttons is clicked, the event is bubbled up like so:
<ButtonList onButtonPressed={(mins) => { console.log(mins); }} />
In response to this, I want to hide that ButtonList and show another component that is currently hidden. The ButtonList has some state such as "state { visible: true }" that I want to toggle that stops it rendering. How do I make a call to toggle the state of that ButtonList and then also call my other component in this view to also toggle its visible state to show?
Thanks.
swappingComponentsExample = () => {
return (
<View>
{this.state.showButtonList ? (
<ButtonList
onButtonPressed={mins => {
this.setState({showButtonList: false});
console.log(mins);
}}
/>
) : (
<OtherComponent />
)}
</View>
);
};
// Renders both components but passes style override to hide the object
// ButtonList/OtherComponent are not destroyed and recreated using this method
hidingExample = () => {
return (
<View>
<ButtonList
onButtonPressed={mins => {
this.setState({showButtonList: false});
console.log(mins);
}}
style={!this.state.showButtonList && {display: 'none'}}
/>
<OtherComponent
style={this.state.showButtonList && {display: 'none'}}
/>
</View>
);
};