Я разработчик React, и я впервые имею дело с React-native. У меня возникла досадная проблема, с которой я застрял на 2 дня.
У меня есть этот компонент:
imports
const OrderDetails = ({route}) => {
const {OrderNumber} = route.params;
const [items, setItems] = useState(null);
const navigation = useNavigation();
useEffect(() => {
const fetchItemDetails = async () => {
try {
const response = await axios.get(
`http://192.168.X.XX:5000/orders/${OrderNumber}`,
);
setItems(response.data);
const handleScannerStatus = data => {
onBarcodeScan(data.data, response.data.items);
};
RegisterScanner(handleScannerStatus);
} catch (error) {
console.info('error fetching order');
}
};
fetchItemDetails();
return () => {
console.info('component unmounted');
UnregisterScanner();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [OrderNumber]);
const onBarcodeScan = async (barcode, items) => {
console.info("Scanning barcode from OrderDetails");
const matchedProduct = items.find(item => barcode === item.tag);
if (matchedProduct.Type === 'kit') {
navigation.navigate('KitDetails', {
OrderNumber,
kit: matchedProduct,
});
}
};
return (my jsx)
};
const styles = {...mystyles}
export default OrderDetails;
этот компонент в основном извлекает заказ и регистрирует событие, которое прослушивает отправку моего собственного модуля, и всякий раз, когда он находит элемент в заказе, который является комплектом, мы переходим к компоненту kitDetails, который выглядит следующим образом:
improts
const KitDetailsScreen = ({route}) => {
const {OrderNumber, kit} = route.params;
useEffect(() => {
let handleScannerStatus = data => {
console.info('Logging Barcode From KitDetails');
};
RegisterScanner(handleScannerStatus);
return () => {
console.info('unregister here');
UnregisterScanner();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const tableHead = ['SKU', 'Fulfilled'];
const tableData = kit.items.map(orderItem => [
orderItem.sku,
`${orderItem.Fulfilled}`,
]);
return (jsx);
};
const styles = {...}
export default KitDetailsScreen;
Также я не думаю, что это будет иметь значение, но вот еще и прослушиватель событий:
import {NativeEventEmitter, NativeModules} from 'react-native';
const {BarcodeScannerModule} = NativeModules;
const eventEmitter = new NativeEventEmitter(BarcodeScannerModule);
export const RegisterScanner = handleScannerStatus => {
eventEmitter.addListener('onBarcodeScanned', handleScannerStatus);
BarcodeScannerModule.registerScannerStatusListener();
};
export const UnregisterScanner = () =>
BarcodeScannerModule.unregisterScannerStatusListener();
Оба экрана выглядят очень похоже, но это не главное. Проблема здесь в том, что всякий раз, когда я перехожу к kitDetails, я все еще вижу console.infos из OrderDetails, я хочу, чтобы всякий раз, когда я перехожу к kitDetails, событие было отменено, и чтобы оно было доступно только в kitDetails, но навигация работает в странно, что он этого не делает.
Когда я начинаю сканирование внутри моего компонента kitDetails, вот результат:
LOG Logging Barcode From OrderDetails
LOG Logging Barcode From KitDetails
LOG Logging Barcode From OrderDetails
LOG Logging Barcode From KitDetails
LOG Logging Barcode From OrderDetails
LOG Logging Barcode From KitDetails
вместо этого он должен отображать только журнал KitDetails. Возможно, из-за того, что я новичок в React-native и что-то упускаю или не совсем понимаю, как работает поток, было бы неплохо дать мне несколько советов. При необходимости я также могу предоставить свой собственный код модуля.
То, что я пробовал и не сработало:
Похоже, вы столкнулись с проблемой, из-за которой прослушиватель событий из компонента OrderDetails все еще активен даже после перехода к компоненту KitDetails. Это происходит потому, что функция очистки компонента OrderDetails, которая отменяет регистрацию прослушивателя событий, не запускается при переходе на другой экран.
Чтобы решить эту проблему, вы можете выполнить следующие шаги:
Переместите регистрацию и отмену регистрации прослушивателя событий сканера за пределы компонента и управляйте им на более высоком уровне, например, в родительском компоненте или контексте.
Используйте событие навигации для запуска функции очистки при выходе из компонента OrderDetails. Вот как вы можете изменить свой код для достижения этой цели:
Переместить регистрацию и отмену регистрации событий: Вместо регистрации и отмены регистрации прослушивателя событий внутри каждого компонента сделайте это на более высоком уровне, например, в родительском компоненте или контексте.
Запустить функцию очистки при навигации: Используйте событие навигации, например useFocusEffect из React Navigation, для запуска функции очистки при выходе из компонента OrderDetails.
Вот пример того, как вы можете выполнить рефакторинг своего кода (внесите изменения в соответствии с именем вашего компонента ):
В итоге я добавил два отдельных события для каждого компонента, и это решило проблему!
спасибо за Ваш ответ! В некоторой степени это сработало: мне удалось успешно отменить регистрацию получателя в OrderDetails, но после того, как я зарегистрировал его обратно в KitDetails, я все еще могу видеть журналы. Это очень странное поведение, как будто это один компонент из двух разных файлов, я даже пытался это использовать: if (isFocused) { onBarcodeScan(data.data, response.data.items) } внутри OrderDetails, и когда я перейти в kitDetails Я все еще вижу лог, даже через эту проверку он все еще справляется, он вроде не расфокусируется, как навигация их так объединяет, я не понимаю?