admin管理员组

文章数量:1327660

Hi I have the following class where I am trying to get the photos from camera roll and display it.

class CameraRollProject extends Component {
  constructor(props) {
    super(props);
    this.state = {
     images: []
    };
  }

  ponentWillMount() {
    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;

The issue is my render function is getting called before my CameraRoll.getPhotos promise get resolved. So I don't get any photos.

To solve this issue I changed my program into following

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>
          );
        });
  }

However this give me the following error

What can I do in above situation? How can I make sure the render only works after the CameraRoll.getPhotos get resolved.

Hi I have the following class where I am trying to get the photos from camera roll and display it.

class CameraRollProject extends Component {
  constructor(props) {
    super(props);
    this.state = {
     images: []
    };
  }

  ponentWillMount() {
    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;

The issue is my render function is getting called before my CameraRoll.getPhotos promise get resolved. So I don't get any photos.

To solve this issue I changed my program into following

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>
          );
        });
  }

However this give me the following error

What can I do in above situation? How can I make sure the render only works after the CameraRoll.getPhotos get resolved.

Share Improve this question edited Sep 7, 2016 at 19:41 Muhammad Raihan Muhaimin asked Sep 7, 2016 at 18:17 Muhammad Raihan MuhaiminMuhammad Raihan Muhaimin 5,7197 gold badges49 silver badges70 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5

So I resolved this issue. The main reason for my problem was I was not using CameraRoll.getPhotos properly as a Promise. I was passing incorrect parameter inside the function. To solve this I got rid of the following functions

 storeImages(data) {
    const assets = data.edges;
    const images = assets.map((asset) => asset.node.image);
    this.state.images =  images;
  }

  logImageError(err) {
    console.log(err);
  }

And make my CameraRoll.getPhotos like the following

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);
  }
);

Here is my plete code to get pictures from CameraRoll in react-native just in case anyone interested

class CameraRollProject extends Component {
  constructor(props) {
    super(props);
    this.state = {
     images: [],
     isCameraLoaded: false
    };
  }

  ponentWillMount() {
    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;

I think you should use react-native-image-picker

You have many parameters to retrieve a picture as you wish

  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
      }
    }

it is much easier to handle than CameraRollProject, and the documentation is very well explained. for what you would do it suits perfectly. (It works on iOS and Android)

One way to do this would be to use a ListView rather than a Scrollview because you can utilize a datasource. Here is a sample of how you could do this:

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);
  });
}

This way, you render an empty list (and a loading state for good UX) and then once the fetch has pleted you set the data in the ListView.

If you want to stick with the ScrollView and the mapped images, you would also need some sort of loading state until the photos load. Hope this helps.

本文标签: javascriptReact Native CameraRollgetPhotos API doesn39t render the resultsStack Overflow