selectedIndex not working properly in iOS
it's working fine in index 0, but when I set different index, it appears as the video shows
https://github.com/user-attachments/assets/202fedce-40f1-4ab8-9b81-a61287907956
Yup, experiencing the same, it is selecting an in between index on initial render if we do not render index 0
Try to change:
const [scrollY] = useState(new Animated.Value(0));
into:
const [scrollY] = useState(new Animated.Value((selectedIndex ?? 0) * itemHeight));
inside WheelPicker.tsx
I have the similar issue when switch to React Native hermes engine.
Possible Root Cause
I doubt it's because in WheelPicker.tsx, the useEffect for scrollToIndex finishes before animated attributes (e.g. scale) in WheelPickerItem.tsx ready.
https://github.com/erksch/react-native-wheely/blob/4a13bfbfded7a3041372098fc519bc19cca91e86/src/WheelPicker.tsx#L105-L114
https://github.com/erksch/react-native-wheely/blob/4a13bfbfded7a3041372098fc519bc19cca91e86/src/WheelPickerItem.tsx#L76-L94
Potential Solution
Therefore, I add a setTimeout in useEffect to put this method into microtask queue, which solves my problem.
Here is the patch:
diff --git a/lib/WheelPicker.js b/lib/WheelPicker.js
index 575325b00e392692a69016b0e66b08c57825b229..9171f6d218b927fb5cc1517cd4267a9fe42ec8f9 100644
--- a/lib/WheelPicker.js
+++ b/lib/WheelPicker.js
@@ -67,11 +67,15 @@ const WheelPicker = ({ selectedIndex, options, onChange, selectedIndicatorStyle
* This ensures that what the user sees as selected in the picker always corresponds to the value state.
*/
(0, react_1.useEffect)(() => {
- var _a;
- (_a = flatListRef.current) === null || _a === void 0 ? void 0 : _a.scrollToIndex({
- index: selectedIndex,
- animated: false,
- });
+ var timer = setTimeout(() => {
+ var _a;
+
+ (_a = flatListRef.current) === null || _a === void 0 ? void 0 : _a.scrollToIndex({
+ index: selectedIndex,
+ animated: false,
+ });
+ }, 0);
+ return () => clearTimeout(timer);
}, [selectedIndex]);
return (react_1.default.createElement(react_native_1.View, Object.assign({ style: [WheelPicker_styles_1.default.container, { height: containerHeight }, containerStyle] }, containerProps),
react_1.default.createElement(react_native_1.View, { style: [
Result
| Before | After |
|---|---|
I initially used timer fix, but on some devices and cases it was not working at the end. I guess it can be combined with what I proposed. Nevertheless interesting case :)
I initially used timer fix, but on some devices and cases it was not working at the end. I guess it can be combined with what I proposed. Nevertheless interesting case :)
@lorenc-tomasz sad to hear that :( I firstly tried your solution, but it does not work for my usecase.
I wrapped WheelPicker to make component easier to use. I init with 0 at first, then I use a useEffect to update it.
If I use your solution, which does not make any difference since it's initial value is 0. that's why I think from the useEffect part.
export default function MyWheelPicker({ value, ... }) {
const [selectedIndex, setSelectedIndex] = useState(0);
useEffect(() => {
// get index by value...
setSelectedIndex(index);
}, [indexDataMap, value]);
...
return (
<WheelPicker
selectedIndex={selectedIndex}
...
/>
);
}
So it depends on the use case. Good to know.
I don't have a solution yet, but I wanted to +1 on having this issue not only when loading the list but also when onChange is called. I've tried the solutions mentioned in here (and also this one), as well as trying to figure it out myself, but no success so far. I'll update the thread with a solution if I find one
Edit: The fix @lorenc-tomasz suggested solved the issue for me! Thanks
https://github.com/user-attachments/assets/65040d60-c085-49aa-b26d-f42211579815