-1

Trying to open Detail screen with static content using native-base components , in iOS it's working fine but in android i was getting problem related to "Roboto-medium" font , so after R&D i came to know that I have to import that font module from native base using Font.loadAsync method. So i use async and await methods to load the fonts from native-base library.Now when ever I am trying to setState of Products after loading font from native-base my render function does not get called again , i do not know that why it's not getting called , as setState always call render method itself.

Here is my component :-

    import React, { Component } from 'react';
    import { Image, Dimensions, TouchableWithoutFeedback, AsyncStorage,StyleSheet,Text} from 'react-native';
    import { View, Root, Container, Content, Button, Left, Right, Icon, Picker, Item, Grid, Col, Toast,TextRN } from 'native-base';
    import Carousel, { Pagination } from 'react-native-snap-carousel';
    import { Font, AppLoading } from "expo";
    export default class Product extends Component {

      constructor(props) {
        super(props);
        this.state = {
          product: {},
          activeSlide: 0,
          quantity: 1,
          selectedColor: '',
          selectedSize: '',
          loading: true 
        };
      }
      static route = {
        navigationBar: {
          title: 'ProductDetail',
          tintColor: '#FFF',
        },
      };
       async componentWillMount() {
         await Font.loadAsync({
           Roboto: require("native-base/Fonts/Roboto.ttf"),
           Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf")
         });
         this.setState({ loading: false, product: dummyProduct});

           alert(JSON.stringify(this.state.product));  
         if (this.state.product.length > 0) {
           let defColor = this.state.product.colors[0];
           let defSize = this.state.product.sizes[0];
           this.setState({
             selectedColor: defColor,
             selectedSize: defSize
           });
         } 
      } 



      render() {
        if (this.state.product.length <= 0) { 
          return (
            <Text>Loading</Text>
          );
        }
        return(

          <Container style={{backgroundColor: '#fdfdfd'}}>

            <Content>
              <Carousel
                  ref={(carousel) => { this._carousel = carousel; }}
                  sliderWidth={Dimensions.get('window').width}
                  itemWidth={Dimensions.get('window').width}
                  onSnapToItem={(index) => this.setState({ activeSlide: index }) }
                  enableSnap={true}
                >
                    {this.renderImages()}
                </Carousel>
                <Pagination
                  dotsLength={this.state.product.images.length}
                  activeDotIndex={this.state.activeSlide}
                  containerStyle={{ backgroundColor: 'transparent',paddingTop: 0, paddingBottom: 0, marginTop: -15 }}
                  dotStyle={{
                      width: 10,
                      height: 10,
                      borderRadius: 5,
                      marginHorizontal: 2,
                      backgroundColor: 'rgba(255, 255, 255, 0.92)'
                  }}
                  inactiveDotOpacity={0.4}
                  inactiveDotScale={0.6}
                />
              <View style={{backgroundColor: '#fdfdfd', paddingTop: 10, paddingBottom: 10, paddingLeft: 12, paddingRight: 12, alignItems: 'center'}}>
                <Grid>
                  <Col size={3}>
                    <TextRN style={{ fontSize: 18 }}>{this.state.product.title}</TextRN>
                  </Col>
                  <Col>
                    <TextRN style={{ fontSize: 20, fontWeight: 'bold' }}>{this.state.product.price}</TextRN>
                  </Col>
                </Grid>
                <Grid style={{marginTop: 15}}>
                  <Col>
                    <View style={{flex: 1, justifyContent: 'center'}}>
                      <TextRN>Color:</TextRN>
                    </View>
                  </Col>
                  <Col size={3}>
                    <Picker
                      mode="dropdown"
                      placeholder="Select a color"
                      note={true}
                      selectedValue={this.state.selectedColor}
                      onValueChange={(color) => this.setState({selectedColor: color})}
                    >
                      {this.renderColors()}
                    </Picker>
                  </Col>
                </Grid>
                <Grid>
                  <Col>
                    <View style={{flex: 1, justifyContent: 'center'}}>
                      <TextRN>Size:</TextRN>
                    </View>
                  </Col>
                  <Col size={3}>
                    <Picker
                      mode="dropdown"
                      placeholder="Select a size"
                      note={true}
                      selectedValue={this.state.selectedSize}
                      onValueChange={(size) => this.setState({selectedSize: size})}
                    >
                      {this.renderSize()}
                    </Picker>
                  </Col>
                </Grid>
                <Grid>
                  <Col>
                    <View style={{flex: 1, justifyContent: 'center'}}>
                      <TextRN>Quantity:</TextRN>
                    </View>
                  </Col>
                  <Col size={3}>
                    <View style={{flex: 1, flexDirection: 'row'}}>
                      <Button style={{flex: 1}} icon light onPress={() => this.setState({quantity: this.state.quantity>1 ? this.state.quantity-1 : 1})} >
                        <Icon name='ios-remove-outline' />
                      </Button>
                      <View style={{flex: 4, justifyContent: 'center', alignItems: 'center', paddingLeft: 30, paddingRight: 30}}>
                        <TextRN style={{ fontSize: 18 }}>{this.state.quantity}</TextRN>
                      </View>
                      <Button style={{flex: 1}} icon light onPress={() => this.setState({quantity: this.state.quantity+1})}>
                        <Icon name='ios-add' />
                      </Button>
                    </View>
                  </Col>
                </Grid>
                <Grid style={{marginTop: 15}}>
                  <Col size={3}>
                    <Button block onPress={this.addToCart.bind(this)} style={{backgroundColor: '#2c3e50'}}>
                      <TextRN style={{ color: "#fdfdfd", marginLeft: 5 }}>Add to cart</TextRN>
                    </Button>
                  </Col>
                  <Col>
                  <Button block onPress={this.addToWishlist.bind(this)} icon transparent style={{backgroundColor: '#fdfdfd'}}>
                    <Icon style={{color: '#2c3e50'}} name='ios-heart' />
                  </Button>
                  </Col>
                </Grid>
                <View style={{marginTop: 15, padding: 10, borderWidth: 1, borderRadius: 3, borderColor: 'rgba(149, 165, 166, 0.3)'}}>
                  <TextRN style={{ marginBottom: 5 }}>Description</TextRN>
                  <View style={{width: 50, height: 1, backgroundColor: 'rgba(44, 62, 80, 0.5)', marginLeft: 7, marginBottom: 10}} />
                  <TextRN note>
                    {this.state.product.description}
                  </TextRN>
                </View>
              </View>
              <View style={{marginTop: 15, paddingLeft: 12, paddingRight: 12}}>
                <TextRN style={{ marginBottom: 5 }}>Similar items</TextRN>
                <View style={{width: 50, height: 1, backgroundColor: 'rgba(44, 62, 80, 0.5)', marginLeft: 7, marginBottom: 10}} />

              </View>
            </Content>

          </Container>
        );


      }

 renderImages() {
    let images = [];
    this.state.product.images.map((img, i) => {
      images.push(
          <TouchableWithoutFeedback
            key={i}
            onPress={() => this.openGallery(i)}
          >
            <Image
              source={{uri: img}}
              style={{width: Dimensions.get('window').width, height: 350}}
              resizeMode="cover"
            />
          </TouchableWithoutFeedback>
      );
    });
    return images;
  }
    }

    const dummyProduct = {
      id: 2,
      title: 'V NECK T-SHIRT',
      description: "Pellentesque orci lectus, bibendum iaculis aliquet id, ullamcorper nec ipsum. In laoreet ligula vitae tristique viverra. Suspendisse augue nunc, laoreet in arcu ut, vulputate malesuada justo. Donec porttitor elit justo, sed lobortis nulla interdum et. Sed lobortis sapien ut augue condimentum, eget ullamcorper nibh lobortis. Cras ut bibendum libero. Quisque in nisl nisl. Mauris vestibulum leo nec pellentesque sollicitudin. Pellentesque lacus eros, venenatis in iaculis nec, luctus at eros. Phasellus id gravida magna. Maecenas fringilla auctor diam consectetur placerat. Suspendisse non convallis ligula. Aenean sagittis eu erat quis efficitur. Maecenas volutpat erat ac varius bibendum. Ut tincidunt, sem id tristique commodo, nunc diam suscipit lectus, vel",
      image: 'http://res.cloudinary.com/atf19/image/upload/c_crop,h_250,w_358,x_150/v1500465309/pexels-photo-206470_nwtgor.jpg',
      images: [
        'http://res.cloudinary.com/atf19/image/upload/c_crop,h_250,w_358,x_150/v1500465309/pexels-photo-206470_nwtgor.jpg',
        'http://res.cloudinary.com/atf19/image/upload/c_crop,h_250,x_226,y_54/v1500465309/pexels-photo-521197_hg8kak.jpg',
        'http://res.cloudinary.com/atf19/image/upload/c_crop,g_face,h_250,x_248/v1500465308/fashion-men-s-individuality-black-and-white-157675_wnctss.jpg',
        'http://res.cloudinary.com/atf19/image/upload/c_crop,h_250/v1500465308/pexels-photo-179909_ddlsmt.jpg'
      ],
      price: '120$',
      colors: ['Red', 'Blue', 'Black'],
      sizes: ['S', 'M', 'L', 'XL', 'XXL'],
      category: 'MAN',
      similarItems: [
        {id: 10, title: 'V NECK T-SHIRT', price: '29$', image: 'http://res.cloudinary.com/atf19/image/upload/c_crop,g_face,h_250,x_248/v1500465308/fashion-men-s-individuality-black-and-white-157675_wnctss.jpg'},
        {id: 11, title: 'V NECK T-SHIRT', price: '29$', image: 'http://res.cloudinary.com/atf19/image/upload/c_crop,h_250/v1500465308/pexels-photo-179909_ddlsmt.jpg'},
        {id: 12, title: 'V NECK T-SHIRT', price: '29$', image: 'http://res.cloudinary.com/atf19/image/upload/c_crop,h_250/v1500465308/pexels-photo-179909_ddlsmt.jpg'}
      ]
    };

Please let me know that why i am getting this error :-

undefined is not an object (evaluating 'this.state.product.images.map')

why it is undefined as i am setting state it should call render method again.

I am new to react and trying to make demo so that i can learn it.

Any Help would be Appreciated!!!!

Regards

user2028
  • 163
  • 4
  • 15
  • 40

1 Answers1

2

I'm not sure i could help or not. Because you're not provide full source code, that's difficult to find out the problem from.

But what I found out is about Carousel, you should render your item in Carousel as data and renderItem as example below:

<Carousel
    data={this.state.product.images}
    renderItem={this.renderImages}
    ref={(carousel) => { this._carousel = carousel; }}
    sliderWidth={Dimensions.get('window').width}
    itemWidth={Dimensions.get('window').width}
    onSnapToItem={(index) => this.setState({ activeSlide: index }) }
    enableSnap={true}
/>

for renderImages()

renderImages({item, index}) {
    return(
        <TouchableWithoutFeedback key={index}>
            <Image
                source={{uri: item}}
                style={{width: Dimensions.get('window').width, height: 350}}
                resizeMode="cover"
            />
        </TouchableWithoutFeedback>
    );
}

Hope it will provide you more information and find some solution. And you can checking more detail how to using react-native-snap-carousel below:

https://github.com/archriss/react-native-snap-carousel

Seyha
  • 323
  • 4
  • 12