React Native 从状态数组中删除多个项目
React native delete multiple items from state array
我有一个目录,用于存储使用相机拍摄的图像。为了保存图像,我使用 RNFS. I am using react-native-photo-browser.
图库本身没有任何选项可用于从图库中删除项目。所以我正在努力实现它
export default class GridGallery extends React.Component{
static navigationOptions = {
title: 'Image Gallery',
};
constructor(props) {
super(props)
this.state = {
filesList : [],
mediaSelected: [],
base64URI: null,
galleryList: []
}
}
componentDidMount(){
FileList.list((files) => {
if(files != null) {
this.fileUrl = files[0].path;
files = files.sort((a, b) => {
if (a.ctime < b.ctime)
return 1;
if (a.ctime > b.ctime)
return -1;
return 0;
});
this.setState({
filesList: files
});
}
console.warn(this.state.filesList);
this.getFiles();
});
}
getFiles(){
//console.warn(this.state.filesList);
const ArrFiles = this.state.filesList.map((file) =>
({ caption : file.name, photo : file.path })
);
//console.warn(ArrFiles);
this.setState({ galleryList : ArrFiles });
}
onActionButton = (media, index) => {
if (Platform.OS === 'ios') {
ActionSheetIOS.showShareActionSheetWithOptions(
{
url: media.photo,
message: media.caption,
},
() => {},
() => {},
);
} else {
alert(`handle sharing on android for ${media.photo}, index: ${index}`);
}
};
handleSelection = async (media, index, isSelected) => {
if (isSelected == true) {
this.state.mediaSelected.push(media.photo);
} else {
this.state.mediaSelected.splice(this.state.mediaSelected.indexOf(media.photo), 1);
}
console.warn(this.state.mediaSelected);
}
deleteImageFile = () => {
const dirPicutures = RNFS.DocumentDirectoryPath;
//delete mulitple files
console.warn(this.state.mediaSelected);
this.state.mediaSelected.map((file) =>
// filepath = `${dirPicutures}/${file}`
RNFS.exists(`${file}`)
.then( (result) => {
console.warn("file exists: ", result);
if(result){
return RNFS.unlink(`${file}`)
.then(() => {
console.warn('FILE DELETED');
let tempgalleryList = this.state.galleryList.filter(item => item.photo !== file);
this.setState({ galleryList : tempgalleryList })
})
// `unlink` will throw an error, if the item to unlink does not exist
.catch((err) => {
console.warn(err.message);
});
}
})
.catch((err) => {
console.warn(err.message);
})
)
}
renderDelete(){
const { galleryList } = this.state;
if(galleryList.length>0){
return(
<View style={styles.topRightContainer}>
<TouchableOpacity style={{alignItems: 'center',right: 10}} onPress={this.deleteImageFile}>
<Image
style={{width: 24, height: 24}}
source={require('../assets/images/ic_delete.png')}
/>
</TouchableOpacity>
</View>
)
}
}
goBack() {
const { navigation } = this.props;
navigation.pop;
}
render() {
const { galleryList } = this.state;
return (
<View style={styles.container}>
<View style={{flex: 1}}>
<PhotoBrowser
mediaList={galleryList}
enableGrid={true}
displayNavArrows={true}
displaySelectionButtons={true}
displayActionButton={true}
onActionButton={this.onActionButton}
displayTopBar = {true}
onSelectionChanged={this.handleSelection}
startOnGrid={true}
initialIndex={0}
/>
</View>
{this.renderDelete()}
</View>
)
}
}
图像列表示例:
[
{
photo:'4072710001_f36316ddc7_b.jpg',
caption: 'Grotto of the Madonna',
},
{
photo: /media/broadchurch_thumbnail.png,
caption: 'Broadchurch Scene',
},
{
photo:
'4052876281_6e068ac860_b.jpg',
caption: 'Beautiful Eyes',
},
]
我的目标是,每当状态 galleryList
中的项目被删除时,我需要刷新组件,以便删除的图像将从图库中删除。因此,当我尝试使用 galleryList
过滤器时,它会删除其他图像而不是其他图像:
let tempgalleryList = this.state.galleryList.filter(item => item.photo !== file);
this.setState({ galleryList : tempgalleryList })
MCVE -> 这是我的代码的缩小版,你可以看到图像随机删除
问题
let tempgalleryList = this.state.galleryList.filter(item => item.photo !== file);
this.setState({ galleryList : tempgalleryList })
由于 setState
是异步的,this.state.galleryList
不会在你的 map
函数的每次迭代中更新,所以最终更新的状态只会过滤掉一个项目而不是全部选定的项目。
解决方案
您可以使用使用更新状态的 callback version of setState
:
this.setState(prevState => ({
galleryList : prevState.galleryList.filter(item => item.photo !== file),
}));
备选方案
不是在每次迭代中都调用 setState
,而是可以在 map
函数之外调用它(尽管 setState
更新无论如何都会被分批处理,因此没有显着的性能改进):
this.setState(prevState => ({
galleryList : prevState.galleryList.filter(item => !prevState.mediaSelected.includes(item.photo)),
}));
您的代码的其他问题
this.state.mediaSelected.push(media.photo);
} else {
this.state.mediaSelected.splice(this.state.mediaSelected.indexOf(media.photo), 1);
你在这里直接改变你的状态。改为这样做:
this.setState(prevState => ({
mediaSelected: prevState.mediaSelected.concat(media.photo)
}));
this.setState(prevState => ({
mediaSelected: prevState.mediaSelected.filter(e => e != media.photo)
}));
我有一个目录,用于存储使用相机拍摄的图像。为了保存图像,我使用 RNFS. I am using react-native-photo-browser.
图库本身没有任何选项可用于从图库中删除项目。所以我正在努力实现它
export default class GridGallery extends React.Component{
static navigationOptions = {
title: 'Image Gallery',
};
constructor(props) {
super(props)
this.state = {
filesList : [],
mediaSelected: [],
base64URI: null,
galleryList: []
}
}
componentDidMount(){
FileList.list((files) => {
if(files != null) {
this.fileUrl = files[0].path;
files = files.sort((a, b) => {
if (a.ctime < b.ctime)
return 1;
if (a.ctime > b.ctime)
return -1;
return 0;
});
this.setState({
filesList: files
});
}
console.warn(this.state.filesList);
this.getFiles();
});
}
getFiles(){
//console.warn(this.state.filesList);
const ArrFiles = this.state.filesList.map((file) =>
({ caption : file.name, photo : file.path })
);
//console.warn(ArrFiles);
this.setState({ galleryList : ArrFiles });
}
onActionButton = (media, index) => {
if (Platform.OS === 'ios') {
ActionSheetIOS.showShareActionSheetWithOptions(
{
url: media.photo,
message: media.caption,
},
() => {},
() => {},
);
} else {
alert(`handle sharing on android for ${media.photo}, index: ${index}`);
}
};
handleSelection = async (media, index, isSelected) => {
if (isSelected == true) {
this.state.mediaSelected.push(media.photo);
} else {
this.state.mediaSelected.splice(this.state.mediaSelected.indexOf(media.photo), 1);
}
console.warn(this.state.mediaSelected);
}
deleteImageFile = () => {
const dirPicutures = RNFS.DocumentDirectoryPath;
//delete mulitple files
console.warn(this.state.mediaSelected);
this.state.mediaSelected.map((file) =>
// filepath = `${dirPicutures}/${file}`
RNFS.exists(`${file}`)
.then( (result) => {
console.warn("file exists: ", result);
if(result){
return RNFS.unlink(`${file}`)
.then(() => {
console.warn('FILE DELETED');
let tempgalleryList = this.state.galleryList.filter(item => item.photo !== file);
this.setState({ galleryList : tempgalleryList })
})
// `unlink` will throw an error, if the item to unlink does not exist
.catch((err) => {
console.warn(err.message);
});
}
})
.catch((err) => {
console.warn(err.message);
})
)
}
renderDelete(){
const { galleryList } = this.state;
if(galleryList.length>0){
return(
<View style={styles.topRightContainer}>
<TouchableOpacity style={{alignItems: 'center',right: 10}} onPress={this.deleteImageFile}>
<Image
style={{width: 24, height: 24}}
source={require('../assets/images/ic_delete.png')}
/>
</TouchableOpacity>
</View>
)
}
}
goBack() {
const { navigation } = this.props;
navigation.pop;
}
render() {
const { galleryList } = this.state;
return (
<View style={styles.container}>
<View style={{flex: 1}}>
<PhotoBrowser
mediaList={galleryList}
enableGrid={true}
displayNavArrows={true}
displaySelectionButtons={true}
displayActionButton={true}
onActionButton={this.onActionButton}
displayTopBar = {true}
onSelectionChanged={this.handleSelection}
startOnGrid={true}
initialIndex={0}
/>
</View>
{this.renderDelete()}
</View>
)
}
}
图像列表示例:
[
{
photo:'4072710001_f36316ddc7_b.jpg',
caption: 'Grotto of the Madonna',
},
{
photo: /media/broadchurch_thumbnail.png,
caption: 'Broadchurch Scene',
},
{
photo:
'4052876281_6e068ac860_b.jpg',
caption: 'Beautiful Eyes',
},
]
我的目标是,每当状态 galleryList
中的项目被删除时,我需要刷新组件,以便删除的图像将从图库中删除。因此,当我尝试使用 galleryList
过滤器时,它会删除其他图像而不是其他图像:
let tempgalleryList = this.state.galleryList.filter(item => item.photo !== file);
this.setState({ galleryList : tempgalleryList })
MCVE -> 这是我的代码的缩小版,你可以看到图像随机删除
问题
let tempgalleryList = this.state.galleryList.filter(item => item.photo !== file);
this.setState({ galleryList : tempgalleryList })
由于 setState
是异步的,this.state.galleryList
不会在你的 map
函数的每次迭代中更新,所以最终更新的状态只会过滤掉一个项目而不是全部选定的项目。
解决方案
您可以使用使用更新状态的 callback version of setState
:
this.setState(prevState => ({
galleryList : prevState.galleryList.filter(item => item.photo !== file),
}));
备选方案
不是在每次迭代中都调用 setState
,而是可以在 map
函数之外调用它(尽管 setState
更新无论如何都会被分批处理,因此没有显着的性能改进):
this.setState(prevState => ({
galleryList : prevState.galleryList.filter(item => !prevState.mediaSelected.includes(item.photo)),
}));
您的代码的其他问题
this.state.mediaSelected.push(media.photo);
} else {
this.state.mediaSelected.splice(this.state.mediaSelected.indexOf(media.photo), 1);
你在这里直接改变你的状态。改为这样做:
this.setState(prevState => ({
mediaSelected: prevState.mediaSelected.concat(media.photo)
}));
this.setState(prevState => ({
mediaSelected: prevState.mediaSelected.filter(e => e != media.photo)
}));