I'm new to React Native and working on a small project. I'm calling a network call and rendering items in a FlatList. Im getting issue when deleting items because setRenderData method is called continously. How do i prevent this from happening? how do i call it only once? I have tried some solutions but i can't understand where the issue is. Please help me.
export default function TextExtractor() {
const [pickerResponse, setPickerResponse] = useState(null);
const [visible, setVisible] = useState(false);
var [renderData, setRenderData] = useState([]);
const onRemove = id => e => {
setRenderData(renderData.filter(renderData => renderData.Id !== id))
};
const Item = ({ title,id }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
<TouchableOpacity onPress={onRemove(id)}>
<Image
style={{width:30,height:30}}
source={require('../assets/delete.png')}
/>
</TouchableOpacity>
</View>
);
useEffect(() => {
return () => {
setRenderData({});
};
}, []);
const onImageLibraryPress = useCallback(() => {
const options = {
selectionLimit: 1,
mediaType: 'photo',
includeBase64: false,
};
ImagePicker.launchImageLibrary(options, setPickerResponse);
}, []);
const onCameraPress = useCallback(() => {
const options = {
saveToPhotos: true,
mediaType: 'photo',
includeBase64: false,
maxWidth: 500,
maxHeight: 500,
quality: 0.5,
};
ImagePicker.launchCamera(options, setPickerResponse);
}, []);
const handleUploadPhoto = () => {
setVisible(false);
const data = new FormData();
data.append("file_uploaded", {
name: pickerResponse.assets[0].fileName,
type: pickerResponse.assets[0].type,
uri:
Platform.OS === "android"
? pickerResponse.assets[0].uri
: pickerResponse.assets[0].uri.replace("file://", "")
});
var url ='https://bacodetextextract.com/upload/image/';
axios.post(url, data, {headers: {
"Content-Type": "multipart/form-data",
Accept: "application/json"
}})
.then((res) => {
setRenderData(res.data);
console.log(‘RESULT: ',renderData);
})
.catch((err) => {
console.log('error', err);
})
};
const uri = pickerResponse?.assets && pickerResponse.assets[0].uri;
if(uri!==undefined){
handleUploadPhoto();
}
const renderItem = ({ item }) => (
<Item title={item.Text}
id = {item.Id}
/>
);
return (
<View style={styles.screen}>
<ImagePickerAvatar uri={uri} onPress={() => setVisible(true)} />
<FlatList style={styles.usernameText}
data={renderData}
renderItem={renderItem}
keyExtractor={item => item.Id}
/>
<ImagePickerModal
isVisible={visible}
onClose={() => setVisible(false)}
onImageLibraryPress={onImageLibraryPress}
onCameraPress={onCameraPress}
/>
</View>
);
}
});
CodePudding user response:
It's not a problem that setRenderData
is called repeatedly, but there are two problems in your code:
onPress={onRemove(id)}
should beonPress={() => onRemove(id)}
. You need to provide a function as theonPress
property, not the result of calling a function.Whenever you're setting new state based on existing state, it's best practice (and often necessary practice) to use the callback version of the function so that you're operating on up-to-date state. You pass in a function that receives the up-to-date state:
setRenderData(renderData => renderData.filter( renderData => renderData.Id !== id ));
Side note: Part of your code is expecting renderData
to be an array, but another part of your code is doing setRenderData({})
, which will make it a non-array object. It happens that part of the cleanup callback of a useEffect
with no dependencies so that object isn't going to be used by the component (because that cleanup is only done when the component is unmounted), but it's still not best practice. (There's also no need to do that, all state is released when the component is unmounted.)
CodePudding user response:
T.J.Crowder solved your problem with the repeated re-rendering. The second problem is this part of your code:
const onRemove = id => e => {
setRenderData(renderData.filter(renderData => renderData.Id !== id))
};
I don't think id => e=> {}
is a valid syntax, it should be like this:
const onRemove = (id) => {
setRenderData(renderData.filter(renderData => renderData.Id !== id))
};