react-native-bouncy-checkbox
react-native-bouncy-checkbox copied to clipboard
Not toggling after setting disableBuildInState
So I am using react-hook-form for my getting value
(
<BouncyCheckbox
onPress={(value) => {
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
onChange(value);
}}
disableBuiltInState
ref={(ref: any) => (bouncyCheckboxRef = ref)}
fillColor={colors.buttonPrimary}
size={18}
unfillColor={colors.background}
style={{ marginTop: 10, marginLeft: 5 }}
text={label}
isChecked={value}
textStyle={{ fontSize: 18, textDecorationLine: "none" }}
iconStyle={{ borderColor: colors.buttonPrimary, marginRight: -5 }}
{...props}
/>
)
When I enable disableBuiltInState button doesnot toggle. And after resetting it with default value checkedState is showing but when clicked again it does not toggle.
@WrathChaos isn't react-hook-form onChange supposed to work for manual state.?
@WrathChaos
export const CustomCheckBoxInput = ({
control,
name,
label,
...props
}: CustomChecboxProps) => {
return (
<Controller
control={control}
defaultValue={false}
name={name}
render={({
field: { value, onChange, onBlur },
fieldState: { error },
}) => {
console.log(value);
return (
<BouncyCheckbox
onPress={(value) => {
Haptics.notificationAsync(
Haptics.NotificationFeedbackType.Success
);
onChange(value);
}}
fillColor={colors.buttonPrimary}
size={18}
unfillColor={colors.background}
style={{ marginTop: 10, marginLeft: 5 }}
text={label}
textStyle={{ fontSize: 18, textDecorationLine: "none" }}
iconStyle={{ borderColor: colors.buttonPrimary, marginRight: -5 }}
/>
);
}}
/>
);
};
this is working as it is supposed to but When I try to set a default value. It doesn't work after some digging found that we have to disable the builtinstate. But now how should I make that work with react-hook-form?
@WrathChaos isn't react-hook-form onChange supposed to work for manual state.?
Honestly, never worked with react-hook-form I need to research about it
@WrathChaos having hard time to figure out its usage with react-hook-form. Can you please look into this issue. Would be really helpful.
@WrathChaos everything works fine when I tried using expo-checkbox. Can you make a prop available onChangeValue as in expo-checkbox.
I will take a look this evening @bytesagar
@WrathChaos Thank you, will be waiting for your response.
Hello @WrathChaos is there any update on the issue?
same issue, any fix available?
Sorry guys, I didn't have time to look at this.
Can someone give me a minimal reproducible example? so it will make it very fast.
For those having issues with the checkbox not rendering with disableBuiltInState in react native
You can replace the source content in the file 'node_modules\react-native-bouncy-checkbox\build\dist\BouncyCheckbox.js'
with the one provided below, clearly the solution isn't that great but it works for now, give it a try.
Also you will need to handle the isChecked state externally, to restore their states and also handle the state change on onPress.
import * as React from "react";
import { Text, View, Image, Animated, Pressable, } from "react-native";
import styles, { _textStyle } from "./BouncyCheckbox.style";
const defaultCheckImage = require("./check.png");
class BouncyCheckbox extends React.Component {
constructor(props) {
super(props);
this.state = {
initial: true,
check: false,
springValue: new Animated.Value(1),
bounceValue: new Animated.Value(1),
};
}
componentDidMount() {
if (this.props.isChecked != undefined) {
this.setState({ checked: this.props.isChecked || false });
}
}
componentDidUpdate(prevprops, prevState) {
if (this.props.isChecked != undefined && prevState.checked == undefined) {
this.setState({ checked: this.props.isChecked });
this.renderCheckIcon();
this.renderCheckboxText();
}
}
bounceEffect = (value, velocity, bounciness) => {
const { useNativeDriver = true } = this.props;
Animated.spring(this.state.bounceValue, {
toValue: value,
velocity,
bounciness,
useNativeDriver,
}).start();
};
renderCheckIcon = () => {
const { checked, initial } = this.state;
const { size = 25, iconStyle, iconComponent, iconImageStyle, fillColor = "#ffc484", ImageComponent = Image, unfillColor = "transparent", disableBuiltInState, isChecked, innerIconStyle, checkIconImageSource = defaultCheckImage } = this.props;
if (disableBuiltInState && (checked || initial) && isChecked) {
this.state.initial = false;
this.state.checked = isChecked;
} else if (!disableBuiltInState || (!this.state.initial)){
this.state.checked = checked;
}
const statusCheck = this.state.checked;
return (<Animated.View style={[
{ transform: [{ scale: this.state.bounceValue }] },
styles.iconContainer(size, statusCheck, fillColor, unfillColor),
iconStyle,
]}>
<View style={[styles.innerIconContainer(size, fillColor), innerIconStyle]}>
{iconComponent ||
(statusCheck && (<ImageComponent source={checkIconImageSource} style={[styles.iconImageStyle, iconImageStyle]}/>))}
</View>
</Animated.View>);
};
renderCheckboxText = () => {
const { text, textComponent, textStyle, textContainerStyle, disableText = false } = this.props;
const { checked } = this.state;
const checkDisableTextType = typeof disableText === "undefined";
return ((!disableText || checkDisableTextType) &&
(textComponent || (<View style={[styles.textContainer, textContainerStyle]}>
<Text style={[
_textStyle(checked),
textStyle,
]}>
{text}
</Text>
</View>)));
};
handleCheck = () => {
const { checked } = this.state;
this.setState({ checked: !checked }, () => {
this.props.onPress && this.props.onPress(this.state.checked);
});
};
render() {
const { style, bounceEffectIn = 0.9, bounceEffectOut = 1, bounceVelocityIn = 0.1, bounceVelocityOut = 0.4, bouncinessIn = 20, bouncinessOut = 20, TouchableComponent = Pressable } = this.props;
return (<TouchableComponent {...this.props} style={[styles.container, style]} onPressIn={() => {
this.bounceEffect(bounceEffectIn, bounceVelocityIn, bouncinessIn);
}} onPressOut={() => {
this.bounceEffect(bounceEffectOut, bounceVelocityOut, bouncinessOut);
}} onPress={() => this.handleCheck()}>
{this.renderCheckIcon()}
{this.renderCheckboxText()}
</TouchableComponent>);
}
}
export default BouncyCheckbox;
//# sourceMappingURL=BouncyCheckbox.js.map
Cheers
Hello @Exhigh Can you create a PR with this fix? we can make it better together if you don't mind
Came here because this issue ate up my entire day as well.
Tried the code segment provided by @Exhigh but was unable to get it to run. Kept getting "Text must be within <Text> component" (points to row 5373 of node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev/js) whenever using disableBuiltInState but the button works as expected when assuming starting state is known at load time.
This package is great but if the value can't be updated via state change call then unfortunately it has needlessly limited use.
** I see your response is typically to ask if I wanted to do manual updates via another button click and I don't. The component should be tied to a state that can be updated whenever the state is updated.
minimal reproducible example:
import BouncyCheckbox from "react-native-bouncy-checkbox";
import React, {Component, useState, useEffect} from 'react';
const AccountSettings = ({nav}) =>{
const [mySetting, setMySetting] = useState(false);
async function updateToggle(){
setMySetting(true);
}
useEffect(()=>{
updateToggle();
},[]);
return(<BouncyCheckbox
size={25}
fillColor="red"
unfillColor="#FFFFFF"
text="Does this package work as expected?"
isChecked={mySetting}
iconStyle={{ borderColor: "red" }}
innerIconStyle={{ borderWidth: 2 }}
textStyle={{ fontFamily: "JosefinSans-Regular" }}
onPress={(isChecked: boolean) => {}}
/>);
}
EXPECTED OUTCOME: BouncyCheckbox is true / checked ACTUAL OUTCOME: BouncyCheckbox is false / unchecked
*** For anyone else that is hard stuck and NEEDS a quick fix you can:
{mySettings ? <checkbox stuff isChecked={true}> : <></>} {!mySettings ? <checkbox stuff isChecked={false}> : <></>}
is the only method I could get to work.
***** The quick fix posted above doesn't show the animation based on the nature of the state change. Just use a touchable opacity with a background color instead until the state update is fixed.
Thank you for providing awesome information @DaneHoward
I will take a look at this tomorrow :)
Came here because this issue ate up my entire day as well.
Tried the code segment provided by @Exhigh but was unable to get it to run. Kept getting "Text must be within component" (points to row 5373 of node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-dev/js) whenever using disableBuiltInState but the button works as expected when assuming starting state is known at load time.
This package is great but if the value can't be updated via state change call then unfortunately it has needlessly limited use.
** I see your response is typically to ask if I wanted to do manual updates via another button click and I don't. The component should be tied to a state that can be updated whenever the state is updated.
Could you try reducing the size of the text, also the react version I am using is version "0.68.2". The error seems to be the fact that the text content cannot seem to render within the text box. Also it seems like you haven't disabledbuiltinstate which sort of is necessary to be able to set your own state and once you do that you will need to change onPressed to change the value of mySetting so that it's value changes rather than isChecked's value.
Hello @Exhigh Can you create a PR with this fix? we can make it better together if you don't mind
The thing is I have moved from working on the project that I was working and well don't necessarily work with react to test any changes. But please do implement the change I suggested but I am not exactly sure how you would convert this code to typescript or just would maintain a separate version for react native in said js form ?
@WrathChaos Any updates on this?
Hello @DaneHoward
As far as I understand you want to handle the whole state part on your own. I checked your example and you were not even using the disableBuiltinState prop. @Exhigh is also mention that.
import React from 'react';
import {SafeAreaView, StyleSheet, Text, View} from 'react-native';
import BouncyCheckbox from 'react-native-bouncy-checkbox';
import RNBounceable from '@freakycoder/react-native-bounceable';
const App = () => {
let bouncyCheckboxRef: BouncyCheckbox | null = null;
const [checkboxState, setCheckboxState] = React.useState(false);
return (
<SafeAreaView
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<View
style={{
height: 30,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 12,
backgroundColor: checkboxState ? '#34eb83' : '#eb4034',
}}>
<Text
style={{
color: '#fff',
}}>{`Check Status: ${checkboxState.toString()}`}</Text>
</View>
<BouncyCheckbox
style={{marginTop: 16}}
ref={(ref: any) => (bouncyCheckboxRef = ref)}
isChecked={checkboxState}
text="Synthetic Checkbox"
disableBuiltInState
onPress={(isChecked: boolean = false) =>
setCheckboxState(!checkboxState)
}
/>
<RNBounceable
style={{
marginTop: 16,
height: 50,
width: '90%',
backgroundColor: '#ffc484',
borderRadius: 12,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() => {
console.log(bouncyCheckboxRef?.onPress());
// bouncyCheckboxRef?.current.onPress();
// bouncyCheckboxRef?.onPress();
}}>
<Text style={{color: '#fff'}}>Synthetic Checkbox Press</Text>
</RNBounceable>
</SafeAreaView>
);
};
const styles = StyleSheet.create({});
export default App;
Can you try this example? You can control checkbox state as you wish like this.
Hello @Exhigh Can you create a PR with this fix? we can make it better together if you don't mind
The thing is I have moved from working on the project that I was working and well don't necessarily work with react to test any changes. But please do implement the change I suggested but I am not exactly sure how you would convert this code to typescript or just would maintain a separate version for react native in said js form ?
Hey @Exhigh,
To be honest I don't like this approach:
componentDidUpdate(prevprops, prevState) {
if (this.props.isChecked != undefined && prevState.checked == undefined) {
this.setState({ checked: this.props.isChecked });
this.renderCheckIcon();
this.renderCheckboxText();
}
}
The component itself should re-render the JSX part, we should not re-call them on our own.
Can you provide me with an example of how come it does not re-render itself?
I just cannot reproduce the problem, I need to see it
Hello @ctriantaf
Can you take a look at the answers and if you're still having the same problem please provide me a minimal example :)
Hi @WrathChaos ,
It seems I had misread the documentation and was waiting for onPress to still pass the state when using disableBuiltinState. I went through the documentation again and it was an easy fix :) Thanks!
Hi @WrathChaos ,
It seems I had misread the documentation and was waiting for
onPressto still pass the state when usingdisableBuiltinState. I went through the documentation again and it was an easy fix :) Thanks!![]()
Love to hear that :) If you need something else please feel free to open an issue :)
Since there is no answer for this, I am going to close it. Please feel free to open another issue if there is still a problem :) I am happy to help/resolve the issue