Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Item Component Collapsed in Flatlist when move to next #35361

Closed
hardikgpatel opened this issue Nov 16, 2022 · 6 comments
Closed

Item Component Collapsed in Flatlist when move to next #35361

hardikgpatel opened this issue Nov 16, 2022 · 6 comments
Labels
Needs: Triage 🔍 Stale There has been a lack of activity on this issue and it may be closed soon.

Comments

@hardikgpatel
Copy link

hardikgpatel commented Nov 16, 2022

Description

I am trying to create a slider using a flatlist; it works fine on most devices, but on the iPhone 12, it misbehaves. The first index item appears correctly, but when I move to the next item, the item container view collapses and all items move to the top of the screen. I have tried both vertical and horizontal scrolling directions. Is there anyone who can assist me in resolving this? I have attached some files for your reference.

phone.number.login.--.still.zoom.in.problem.mp4

iPhone 12 device information

Version

0.64.2

Output of npx react-native info

System:
OS: macOS 11.6
CPU: (12) x64 Intel(R) Core(TM) i5-10400 CPU @ 2.90GHz
Memory: 231.70 MB / 16.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 19.0.1 - /usr/local/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 8.19.2 - /usr/local/bin/npm
Watchman: 2022.11.07.00 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.11.2 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 21.2, iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3
Android SDK:
API Levels: 23, 25, 28, 30, 31, 32
Build Tools: 29.0.2, 30.0.0, 30.0.2, 30.0.3, 31.0.0, 32.0.0
System Images: android-30 | Google Play Intel x86 Atom
Android NDK: Not Found
IDEs:
Android Studio: 2021.2 AI-212.5712.43.2112.8815526
Xcode: 13.2.1/13C100 - /usr/bin/xcodebuild
Languages:
Java: 11.0.15 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: ^17.0.2 => 17.0.2
react-native: ^0.64.2 => 0.64.2
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found

Steps to reproduce

create a flatlist from the example code given.

Snack, code example, screenshot, or link to a repository

import React, {useContext, useEffect, useRef, useState} from 'react';
import {
View,
SafeAreaView,
FlatList,
TouchableOpacity,
Image,
KeyboardAvoidingView,
Keyboard,
ActivityIndicator,
StyleSheet,
} from 'react-native';
import {useDispatch, useSelector} from 'react-redux';
import {getFilterIds} from '../../../Actions/FeedActions';
import AppImages from '../../../Theme/AppImages';
import CommonStyle from '../../../Theme/CommonStyle';
import {
currentEnv,
isIOS,
phoneNoVerifyHeaderImages,
phoneNoVerifyScreens,
STORAGE,
width,
} from '../../../Utils/Constant';
import {
CustomPhoneInput,
CustomText,
CustomTextInput,
OtpInput,
PaginatedHeader,
} from '../../CommonComponent';
import {CommonActions} from '@react-navigation/native';
import {getErrorMessage, isValidEmail, showToast} from '../../../Utils/Helper';
import {AppContext} from '../../../AppContext';
import {
addFCMToken,
resendCode,
userLogin,
userVerify,
} from '../../../Services/UserService';
import {updateUserDetail} from '../../../Actions/UserActions';
import {getItemFromStorage, setItemInStorage} from '../../../Utils/Storage';
import {ApiConfig} from '../../../ApiConfig';
import {getOnboardData} from '../../../Actions/OnboardActions';
import DeviceInfo from 'react-native-device-info';

let count = 0;

const VerifyPhone = props => {
const {
route: {params},
} = props;
const {appTheme} = useContext(AppContext);
const {
flexContainer,
bottomContainer,
rowCenter,
errorInput,
verificationText,
flexStyle,
} = CommonStyle;
const {itemContainer, titleText, loader, resendContainer} = styles;
const {navigation} = props;
const {user} = useSelector(state => state.user);
const [listIndex, setListIndex] = useState(params?.index ? params.index : 0);
const [error, setError] = useState({});
const [hasError, setHasError] = useState({
email: false,
code: false,
phone: false,
});
const [toggle, setToggle] = useState(false);
const [userData, setUserData] = useState({
email: user?.email || '',
phone: user?.phone || '',
code: '',
unmaskedPhone: user?.unmaskedPhone || '',
countryCode: user?.countryCode || '',
});
const [sendCode, setSendCode] = useState(false);
const dispatch = useDispatch();
let flatListRef = useRef('');

useEffect(() => {
count = 0;
dispatch(getOnboardData());
}, []);

const onTextChange = (key, text, isValid, unmaskedNo, countryCode) => {
if (key && text) {
userData[key] = text;
if (unmaskedNo && countryCode) {
userData.unmaskedPhone = unmaskedNo;
userData.countryCode = countryCode;
}
setUserData(userData);
if (key === 'email' && listIndex === 0 && !params?.index) {
if (!isValidEmail(text)) {
setErrorData(key, 'Enter valid email.', true);
} else if (isValidEmail(text)) {
setErrorData(key, '', false);
}
}

  if (key === 'phone' && listIndex === 1) {
    if (!isValid) {
      setErrorData(key, 'Enter valid phone number.', true);
    } else {
      setErrorData(key, '', false);
    }
  }

  if (key === 'code' && listIndex === 2) {
    setErrorData(key, '', false);
  }
}

};

const setErrorData = (key, msg, value) => {
let errorData = error;
let hasErrorData = hasError;
errorData[key] = msg;
hasErrorData[key] = value;
setHasError(hasErrorData);
setError(errorData);
setToggle(!toggle);
};

const navigateToRoute = (route, params = {}) => {
navigation.dispatch(
CommonActions.reset({
index: 0,
routes: [{name: route, params: params}],
}),
);
};

const getComponentFromType = (item, index) => {
if (item.type === 'textInput') {
return (
<CustomTextInput
placeholder={item.placeholder}
keyboardType={item.keyboardType}
onTextChange={text => {
onTextChange(item.key, text);
}}
value={user[item.key]}
autoCapitalize={'none'}
/>
);
} else if (item.type === 'phoneInput') {
return (
<CustomPhoneInput
onTextChange={(text, isVerified, unmaskedNo, countryCode) => {
onTextChange(item.key, text, isVerified, unmaskedNo, countryCode);
}}
userData={userData}
/>
);
} else {
return (
<OtpInput
digits={6}
value={userData.code}
onChangeOtp={text => onTextChange(item.key, text)}
/>
);
}
};

const updateStorage = async data => {
setItemInStorage('token', data?.token);
ApiConfig.token = data.token;
ApiConfig.streamKey = data.user.streamAppKey;
ApiConfig.streamToken = data.user.streamToken;
};

const clearOTP = () => {
userData.code = '';
error.code = '';
hasError.code = '';
setUserData(userData);
setError(error);
setHasError(hasError);
};

const registerUser = async () => {
try {
if (count === 0) {
count = count + 1;
let registerData = userData;
if (user.provider) {
registerData.provider = user.provider;
registerData.providerId = user.providerId;
}
registerData.register = true;
console.log('registerData', registerData);
const response = await userLogin(registerData);
if (response.status === 'success') {
count = 0;
moveToNext();
// ApiConfig.token = response.data.userItem.activationToken;
// setItemInStorage('token', response.data.userItem.activationToken);
// dispatch(updateUserDetail(response.data.userItem));
// showToast(response.data.code);
}
}
} catch (err) {
if (err?.response?.data) {
count = 0;
setErrorData('phone', getErrorMessage(err), true);
}
}
};

const updateFCMToken = async () => {
const localToken = await getItemFromStorage(STORAGE.fcmToken);
console.log('localToken', localToken);
try {
if (localToken) {
const deviceId = await DeviceInfo.getDeviceId();
const data = {
token: localToken,
platform: isIOS ? 'ios' : 'android',
environment: currentEnv,
deviceId: deviceId,
};
console.log('data register firebase', data);
const repoonse = await addFCMToken(data);
console.log('repoonse', repoonse);
}
} catch (e) {
console.log(e);
}
};

const verifyUser = async () => {
try {
if (count === 0) {
count = count + 1;
let verificationData = userData;
verificationData.register = true;
console.log('verificationData', verificationData);
let response = await userVerify(verificationData);
if (response.status === 'success') {
console.log('response', response);
updateStorage(response.data);
ApiConfig.token = response.data.user.activationToken;
setItemInStorage('token', response.data.user.activationToken);
dispatch(
updateUserDetail({
...userData,
...response?.data?.user,
}),
);
if (response?.data?.user?.isProfileCompleted) {
makeTogetherCall(response?.data?.user);
showToast(
'Phone number already exists. Redirecting to together feeds.',
);
updateFCMToken();
navigateToRoute('Home');
} else {
showToast(response?.message);
navigateToRoute('#');
}
}
}
} catch (err) {
if (err?.response?.data) {
count = 0;
userData.code = '';
setUserData(userData);
setErrorData('code', getErrorMessage(err), true);
}
}
};

const makeTogetherCall = userObj => {
dispatch(getFilterIds({user: userObj}));
};

const moveToNext = () => {
flatListRef?.scrollToIndex({index: listIndex + 1});
setListIndex(listIndex + 1);
};

const scrollToNext = () => {
Keyboard.dismiss();
if (listIndex === 1) {
registerUser();
} else if (listIndex === 2) {
console.log('asdfasdfadsf');
verifyUser();
} else {
moveToNext();
}
};

const scrollToPrevious = () => {
count = 0;
Keyboard.dismiss();
if (listIndex !== 0) {
if (listIndex === 2) {
clearOTP();
}
flatListRef?.scrollToIndex({index: listIndex - 1});
setListIndex(listIndex - 1);
} else {
navigation.goBack();
}
};

const checkError = () => {
let key =
(listIndex !== 0 && ((listIndex === 1 && 'phone') || 'code')) || 'email';

if (key !== 'phone') {
  let condition =
    key === 'email'
      ? hasError[key] || !userData[key]
      : hasError[key] || !userData[key] || userData[key].length !== 6;
  if (condition) {
    return true;
  }
  return false;
} else {
  if (hasError[key] || !userData.unmaskedPhone || !userData.countryCode) {
    return true;
  }
  return false;
}

};

const resendOTP = async () => {
try {
console.log(userData);
setSendCode(true);
const data = {phone: userData.phone, register: true};
const response = await resendCode(data);
if (response.status === 'success') {
clearOTP();
setSendCode(false);
// showToast(response.data.code);
}
} catch (error) {
setSendCode(false);
}
};

const renderItem = ({item, index}) => {
return (


{item.title}

{getComponentFromType(item, index)}
{(hasError[item.key] && (

{error[item.key]}

)) ||
null}
{(item.key === 'code' && (
<TouchableOpacity
style={[rowCenter, resendContainer]}
onPress={() => resendOTP()}>
{(sendCode && (
<ActivityIndicator
size={'small'}
color={appTheme.theme}
style={loader}
/>
)) ||
null}

{sendCode
? 'Sending Verification Code'
: 'Resend Verification Code'}


)) ||
null}

);
};

return (

<KeyboardAvoidingView
behavior={'padding'}
style={flexStyle}
keyboardVerticalOffset={isIOS ? '' : -500}>
<PaginatedHeader
headerImages={phoneNoVerifyHeaderImages}
activeIndex={listIndex}
onPressBack={() => {
scrollToPrevious();
}}
/>

<FlatList
showsHorizontalScrollIndicator={false}
data={phoneNoVerifyScreens}
renderItem={renderItem}
keyExtractor={item => item.id}
horizontal={true}
scrollEnabled={false}
ref={ref => {
flatListRef = ref;
}}
initialScrollIndex={params?.index ? params?.index : 0}
keyboardShouldPersistTaps={'always'}
/>

{(!checkError() && (
<TouchableOpacity
onPress={() => {
scrollToNext();
}}>
<Image
source={{uri: AppImages.next}}
style={CommonStyle.nextImage}
resizeMode="contain"
/>

)) || (
<Image
source={{uri: AppImages.disabled}}
style={CommonStyle.nextImage}
resizeMode="contain"
/>
)}




);
};

const styles = StyleSheet.create({
itemContainer: {
flex: 1,
width: width,
paddingHorizontal: 16,
marginTop: '10%',
},
titleText: {
marginBottom: '10%',
},
loader: {
marginRight: 10,
},
resendContainer: {
marginTop: 10,
},
});

export default VerifyPhone;

@Ahmed-Imam
Copy link

@hardikgpatel any updates on this ??

@hardikgpatel
Copy link
Author

Nop

@Ahmed-Imam
Copy link

@hardikgpatel we found the issue its cause of behavior={'padding'} if you would remove that it will work.
check the comment here for more info #29974 (comment)

@hardikgpatel
Copy link
Author

Okay i will check that

@github-actions
Copy link

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Jul 25, 2023
@github-actions
Copy link

github-actions bot commented Aug 1, 2023

This issue was closed because it has been stalled for 7 days with no activity.

@github-actions github-actions bot closed this as completed Aug 1, 2023
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Needs: Triage 🔍 Stale There has been a lack of activity on this issue and it may be closed soon.
Projects
None yet
Development

No branches or pull requests

2 participants