React Native CameraRoll.getPhotos API не отображает результаты
Привет у меня есть следующий класс, где я пытаюсь получить фотографии с камеры и показать их.
class CameraRollProject extends Component {
constructor(props) {
super(props);
this.state = {
images: []
};
}
componentWillMount() {
const fetchParams = {
first: 25,
};
CameraRoll.getPhotos(fetchParams, this.storeImages, this.logImageError);
}
storeImages(data) {
const assets = data.edges;
const images = assets.map((asset) => asset.node.image);
this.state.images = images;
}
logImageError(err) {
console.log(err);
}
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.imageGrid}>
{ this.state.images.map((image) => <Image style={styles.image} source={{ uri: image.uri }} />) }
</View>
</ScrollView>
);
}
};
export default CameraRollProject;
Проблема в том, что моя функция рендеринга вызывается до того, как мое обещание CameraRoll.getPhotos будет решено. Так что я не получаю никаких фотографий.
Чтобы решить эту проблему, я изменил свою программу на следующие
render() {
return CameraRoll.getPhotos(fetchParams, this.storeImages, this.logImageError)
.then(() => {
return (
<ScrollView style={styles.container}>
<View style={styles.imageGrid}>
{ this.state.images.map((image) => <Image style={styles.image} source={{ uri: image.uri }} />) }
</View>
</ScrollView>
);
});
}
Однако это дает мне следующую ошибку
Что я могу сделать в вышеуказанной ситуации? Как я могу убедиться, что рендер работает только после разрешения CameraRoll.getPhotos.
3 ответа
Поэтому я решил эту проблему. Основной причиной моей проблемы было то, что я не использовал CameraRoll.getPhotos
как обещание. Я передавал неверный параметр внутри функции. Чтобы решить эту проблему, я избавился от следующих функций
storeImages(data) {
const assets = data.edges;
const images = assets.map((asset) => asset.node.image);
this.state.images = images;
}
logImageError(err) {
console.log(err);
}
И сделайте мой CameraRoll.getPhotos как следующий
CameraRoll.getPhotos({first: 5}).then(
(data) =>{
const assets = data.edges
const images = assets.map((asset) => asset.node.image);
this.setState({
isCameraLoaded: true,
images: images
})
},
(error) => {
console.warn(error);
}
);
Вот мой полный код, чтобы получить фотографии с CameraRoll в реагирующем на всякий случай, если кому-то интересно
class CameraRollProject extends Component {
constructor(props) {
super(props);
this.state = {
images: [],
isCameraLoaded: false
};
}
componentWillMount() {
CameraRoll.getPhotos({first: 5}).then(
(data) =>{
const assets = data.edges;
const images = assets.map((asset) => asset.node.image);
this.setState({
isCameraLoaded: true,
images: images
})
},
(error) => {
console.warn(error);
}
);
}
render() {
if (!this.state.isCameraLoaded) {
return (
<View>
<Text>Loading ...</Text>
</View>
);
}
return (
<ScrollView style={styles.container}>
<View style={styles.imageGrid}>
{ this.state.images.map((image) => <Image style={styles.image} source={{ uri: image.uri }} />) }
</View>
</ScrollView>
);
}
};
export default CameraRollProject;
Я думаю, что вы должны использовать ответную реакцию
У вас есть много параметров, чтобы получить изображение, как вы хотите
selectPhotoTapped() {
const options = {
title: 'Choose a picture',
cancelButtonTitle: 'Back',
takePhotoButtonTitle: 'Take a picture...',
chooseFromLibraryButtonTitle: 'Choose from my pictures..',
quality: 1,
maxWidth: 300,
maxHeight: 300,
allowsEditing: true,
mediaType: 'photo',
storageOptions: {
skipBackup: true
}
}
с ним гораздо легче обращаться, чем с CameraRollProject, и документация очень хорошо объяснена. для того, что бы вы делали, это прекрасно подходит. (Работает на iOS и Android)
Одним из способов сделать это было бы использовать ListView
а не Scrollview
потому что вы можете использовать datasource
, Вот пример того, как вы могли бы сделать это:
constructor(props) {
super(props);
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
this.state = { dataSource: ds.cloneWithRows([]) };
this.loadPhotos();
}
loadPhotos() {
const fetchParams = {
first: 25,
};
CameraRoll.getPhotos(fetchParams).then((data) => {
this.state.dataSource.cloneWithRows(data.edges);
}).catch((e) => {
console.log(e);
});
}
Таким образом, вы отображаете пустой список (и состояние загрузки для хорошего UX), а затем, как только выборка завершена, вы устанавливаете данные в ListView
,
Если вы хотите придерживаться ScrollView
и сопоставленные изображения, вам также понадобится какое-то состояние загрузки до загрузки фотографий. Надеюсь это поможет.