Я изучаю реакцию-native/expo.
Когда я что-нибудь печатаю, вся страница перерисовывается. Я знаю это, потому что в коде я загружаю изображение, а в консоли вижу uri изображения. Поэтому, когда я печатаю, я вижу это снова и снова, пока приложение не вылетает.
Я загрузил сюда весь код, потому что он слишком длинный.
Порядок действий: заполните форму, при необходимости загрузите изображение и нажмите кнопку подтверждения.
Я пробовал использовать useCallback, но безуспешно.
МРЭ по запросу:
import React, { useState, useCallback } from 'react';
import { View, TextInput, Text, StyleSheet, TouchableOpacity, Image } from 'react-native';
import KeyboardWrapper from '../KeyboardWrapper';
import * as ImagePicker from 'expo-image-picker';
const FormComponent = ({ onSave }) => {
const [formData, setFormData] = useState({
driverName1: '',
});
const [images, setImages] = useState([]); // State to store captured images
// Function to handle image capture
const handleCaptureImage = useCallback(async () => {
const { status } = await ImagePicker.requestCameraPermissionsAsync();
if (status !== 'granted') {
alert('Camera permission is required to take pictures.');
return;
}
try {
const result = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: false,
aspect: [16, 9],
quality: 1,
});
if (!result.cancelled && result.assets.length > 0) {
// Add the new image URI to the images state
setImages(prevImages => [...prevImages, result.assets[0].uri]);
}
} catch (error) {
console.error('Error capturing image:', error);
}
}, []);
const handleChangeEvent = useCallback((name, value) => {
setFormData({ ...formData, [name]: value });
}, [formData]);
return (
<KeyboardWrapper>
<View style = {styles.container}>
<View style = {styles.form}>
<TextInput
placeholder = "Sofer 1"
value = {formData.driverName1}
onChangeText = {(text) => handleChangeEvent('driverName1', text)}
style = {styles.textInput}
/>
{/* Display captured images */}
<View style = {styles.formImgs}>
{images.map((imageUri, index) => (
<View key = {index} style = {styles.img}>
{console.info('Image URI:', imageUri)}
<Image
source = {{ uri: imageUri }}
style = {{ width: 100, height: 100 }}
/>
</View>
))}
</View>
<View style = {styles.formAction}>
<TouchableOpacity onPress = {handleCaptureImage}>
<View style = {styles.btn}>
<Text style = {styles.btnText}>Scaneaza</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
</KeyboardWrapper>
);
};
@asyncawait только что добавил MRE.
Ссылка на видео гласит: «Это видео не готово. Попросите создателя видео зарегистрироваться и снова поделиться им с вами для предварительного просмотра».
@asyncawait загружено на YouTube. Теперь это должно сработать.





проблема в handlechange, должно быть так
const handleChangeEvent = useCallback((name, event ) => {
setFormData({ ...formData, [name]: event.target.value});
}, [formData]);
Я думаю, вы можете путать TextInput с типом ввода = «текст». TextInput — это собственный компонент, который имеет обработчик событий onChangeText и не возвращает событие в качестве первого аргумента для этого обработчика, а передает сам текст.
Я считаю, что повторный рендеринг компонентов — это функция React по умолчанию. Если вам нужен более детальный контроль над повторной визуализацией вашего компонента, вам, вероятно, нужен React.memo. Обертывание компонента в это предотвратит его повторный рендеринг по умолчанию.
const { useState, memo } = React;
const ImgDisplay = memo(({ imgs }) => {
console.info("rendering ImgDisplay");
return (
<div>
{
imgs.map((img, i) => <div key = {i}>{img}</div>)
}
</div>
)
})
const Example = () => {
const [images, setImages] = useState([]);
const [txt, setTxt] = useState("");
const captureImage = () => {
const randomNumberForImagePlaceholder = Math.floor(Math.random() * 100);
setImages(imgs => [...imgs, randomNumberForImagePlaceholder]);
};
return (
<div>
<input
type = "text"
onChange = {e => setTxt(e.target.value)}
/>
<ImgDisplay imgs = {images} />
<button onClick = {captureImage}>add image</button>
</div>
)
};
ReactDOM.createRoot(
document.getElementById("root")
).render(
<Example />
);<div id = "root"></div>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>И та же демонстрация, но без заметок, чтобы вы могли видеть журнал, происходящий при изменении ввода.
const { useState, memo } = React;
const ImgDisplay = ({ imgs }) => {
console.info("rendering ImgDisplay");
return (
<div>
{
imgs.map((img, i) => <div key = {i}>{img}</div>)
}
</div>
)
};
const Example = () => {
const [images, setImages] = useState([]);
const [txt, setTxt] = useState("");
const captureImage = () => {
const randomNumberForImagePlaceholder = Math.floor(Math.random() * 100);
setImages(imgs => [...imgs, randomNumberForImagePlaceholder]);
};
return (
<div>
<input
type = "text"
onChange = {e => setTxt(e.target.value)}
/>
<ImgDisplay imgs = {images} />
<button onClick = {captureImage}>add image</button>
</div>
)
};
ReactDOM.createRoot(
document.getElementById("root")
).render(
<Example />
);<div id = "root"></div>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>Я просто хотел добавить: если ввод текста не меняет ничего визуально при вводе, вам, вероятно, понадобится useRef вместо состояния. Это также предотвратит повторный рендеринг вашего компонента.
Сможете ли вы сделать МРЕ?