Skip to content

Commit 73f1805

Browse files
committed
🎉 new: Helper util is here to handle useState async handling
1 parent cb617a5 commit 73f1805

File tree

7 files changed

+158
-9
lines changed

7 files changed

+158
-9
lines changed

example/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React from "react";
2-
import { ViewStyle, SafeAreaView } from "react-native";
2+
import { ViewStyle, SafeAreaView, Alert } from "react-native";
33
import Icon from "react-native-dynamic-vector-icons";
44
import RoundedCheckboxGroup, {
55
ICheckboxButton,
6-
} from "react-native-rounded-checkbox-group";
6+
} from "./lib/RoundedCheckboxGroup";
77

88
const styles = {
99
innerStyle: { height: 45, width: 45, borderRadius: 75 },
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { ViewStyle, StyleSheet } from "react-native";
2+
3+
interface Style {
4+
container: ViewStyle;
5+
}
6+
7+
export default StyleSheet.create<Style>({
8+
container: {
9+
flexDirection: "row",
10+
},
11+
});

example/lib/RoundedCheckboxGroup.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import * as React from "react";
2+
import { View, StyleProp, ViewStyle } from "react-native";
3+
import { PureRoundedCheckbox } from "react-native-rounded-checkbox";
4+
import { IRoundedCheckboxProps } from "react-native-rounded-checkbox/build/dist/functional/RoundedCheckbox";
5+
import useStateWithCallback from "./helpers/useStateWithCallback";
6+
/**
7+
* ? Local Imports
8+
*/
9+
import styles from "./RoundedCheckboxGroup.style";
10+
11+
type CustomStyleProp = StyleProp<ViewStyle> | Array<StyleProp<ViewStyle>>;
12+
13+
export interface ICheckboxButton extends IRoundedCheckboxProps {
14+
id: number;
15+
}
16+
17+
export interface IRoundedCheckboxGroupProps {
18+
style?: CustomStyleProp;
19+
initial?: number;
20+
children?: React.ReactNode;
21+
data: ICheckboxButton[];
22+
component?: (isActive: boolean) => React.ReactNode;
23+
onChange: (selectedItem: ICheckboxButton) => void;
24+
}
25+
26+
const RoundedCheckboxGroup: React.FC<IRoundedCheckboxGroupProps> = ({
27+
style,
28+
data,
29+
initial,
30+
children,
31+
component,
32+
onChange,
33+
}) => {
34+
const [selectedItem, setSelectedItem] = useStateWithCallback<
35+
ICheckboxButton | undefined
36+
>(undefined);
37+
38+
const handleItemPress = (item: ICheckboxButton) => {
39+
setSelectedItem(item, (newItem) => onChange && onChange(newItem));
40+
};
41+
42+
return (
43+
<View style={[styles.container, style]}>
44+
{data &&
45+
data.map((item: ICheckboxButton) => {
46+
const isActive =
47+
item.id === (selectedItem ? selectedItem?.id : initial);
48+
return (
49+
<PureRoundedCheckbox
50+
{...item}
51+
key={item.id}
52+
active={isActive}
53+
onPress={() => handleItemPress(item)}
54+
>
55+
{component ? component(isActive) : children}
56+
</PureRoundedCheckbox>
57+
);
58+
})}
59+
</View>
60+
);
61+
};
62+
63+
export default RoundedCheckboxGroup;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {
2+
useRef,
3+
useState,
4+
useEffect,
5+
useCallback,
6+
SetStateAction,
7+
} from "react";
8+
9+
type Callback<T> = (value?: any) => void;
10+
type DispatchWithCallback<T> = (value: any, callback?: Callback<any>) => void;
11+
12+
function useStateWithCallback<T>(
13+
initialState: any | (() => any),
14+
): [any, DispatchWithCallback<SetStateAction<any>>] {
15+
const [state, _setState] = useState(initialState);
16+
17+
const callbackRef = useRef<Callback<any>>();
18+
const isFirstCallbackCall = useRef<boolean>(true);
19+
20+
const setState = useCallback(
21+
(setStateAction: SetStateAction<any>, callback?: Callback<any>): void => {
22+
callbackRef.current = callback;
23+
_setState(setStateAction);
24+
},
25+
[],
26+
);
27+
28+
useEffect(() => {
29+
if (isFirstCallbackCall.current) {
30+
isFirstCallbackCall.current = false;
31+
return;
32+
}
33+
callbackRef.current?.(state);
34+
}, [state]);
35+
36+
return [state, setState];
37+
}
38+
39+
export default useStateWithCallback;

lib/RoundedCheckboxGroup.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as React from "react";
22
import { View, StyleProp, ViewStyle } from "react-native";
33
import { PureRoundedCheckbox } from "react-native-rounded-checkbox";
44
import { IRoundedCheckboxProps } from "react-native-rounded-checkbox/build/dist/functional/RoundedCheckbox";
5+
import useStateWithCallback from "./helpers/useStateWithCallback";
56
/**
67
* ? Local Imports
78
*/
@@ -30,16 +31,12 @@ const RoundedCheckboxGroup: React.FC<IRoundedCheckboxGroupProps> = ({
3031
component,
3132
onChange,
3233
}) => {
33-
const [selectedItem, setSelectedItem] = React.useState<
34+
const [selectedItem, setSelectedItem] = useStateWithCallback<
3435
ICheckboxButton | undefined
3536
>(undefined);
3637

37-
React.useEffect(() => {
38-
onChange && onChange(selectedItem!);
39-
}, [selectedItem]);
40-
4138
const handleItemPress = (item: ICheckboxButton) => {
42-
setSelectedItem(item);
39+
setSelectedItem(item, (newItem) => onChange && onChange(newItem));
4340
};
4441

4542
return (

lib/helpers/useStateWithCallback.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {
2+
useRef,
3+
useState,
4+
useEffect,
5+
useCallback,
6+
SetStateAction,
7+
} from "react";
8+
9+
type Callback<T> = (value?: any) => void;
10+
type DispatchWithCallback<T> = (value: any, callback?: Callback<any>) => void;
11+
12+
function useStateWithCallback<T>(
13+
initialState: any | (() => any),
14+
): [any, DispatchWithCallback<SetStateAction<any>>] {
15+
const [state, _setState] = useState(initialState);
16+
17+
const callbackRef = useRef<Callback<any>>();
18+
const isFirstCallbackCall = useRef<boolean>(true);
19+
20+
const setState = useCallback(
21+
(setStateAction: SetStateAction<any>, callback?: Callback<any>): void => {
22+
callbackRef.current = callback;
23+
_setState(setStateAction);
24+
},
25+
[],
26+
);
27+
28+
useEffect(() => {
29+
if (isFirstCallbackCall.current) {
30+
isFirstCallbackCall.current = false;
31+
return;
32+
}
33+
callbackRef.current?.(state);
34+
}, [state]);
35+
36+
return [state, setState];
37+
}
38+
39+
export default useStateWithCallback;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-rounded-checkbox-group",
3-
"version": "0.1.0",
3+
"version": "0.1.1",
44
"description": "Fully customizable react native checkbox group for React Native",
55
"main": "./build/dist/RoundedCheckboxGroup.js",
66
"repository": "git@github.com:WrathChaos/react-native-rounded-checkbox-group.git",

0 commit comments

Comments
 (0)