2

I have this React-Native component, which renders an image gallery, in a list. So it's invoked once per each item on that parent list. It receives two props, "etiqueta" which has the title of the item, and "galleries", which is an array of galleries (javascript literals). I know it should only receive the gallery that we need to render, but I couldn't do it, so for now, I'm sending all the galleries and filtering them in this component.

Problem: when I console.log the state in ComponentDidMount everything looks good, state.entries has the gallery that need to be rendered. But when I try to access it in get Example2() it returns an empty array. I'm not sure why this is happening.

And also, for some reason, the console.log in get Example2() keeps running again and again in the console. Why is this happening?

This is the gallery I'm trying to use: https://github.com/archriss/react-native-snap-carousel

Thank you for your time of course, I hope I'm clear enough, I'm new to React.

class EtiquetaDetail extends Component {

  constructor(props) {
    super(props);

    this.state = {
      slider1ActiveSlide: 0,
      slider1Ref: null,
      entries: [],
      isMounted: false
    };
  }

  componentDidMount() {

    let etiqueta_id = this.props.etiqueta.id ;

    if ( this.props.etiqueta ) {

      // select the gallery we need to render
      gallery = this.props.galleries.find(function (obj) {
        return obj.id_gal === etiqueta_id;
      });

      ENTRIES1 = JSON.parse( gallery.data );

      this.setState = {
        slider1ActiveSlide: 0,
        slider1Ref: null,
        entries: ENTRIES1,
        isMounted: true
      };
      console.log(this.state); // this outputs everything as expected

    }

  }

get example2 () {
  console.log(this.state.entries); // returns 0 
    return (
        <View>
            <Carousel
              data={ this.state.entries }
            />
        </View>
    );
}

  render() {

    const etiqueta = this.props;

    const { title } = this.props.etiqueta;

    return (
      <Card>
        <CardSection>
          <View>
            <Text>{title.rendered}</Text>
          </View>
        </CardSection>

        <SafeAreaView>
            <View}>
                <ScrollView>
                    { this.example2 }
                </ScrollView>
            </View>
        </SafeAreaView>

      </Card>
    )
  };

};
kilinkis
  • 584
  • 2
  • 13
  • 26
  • By setting the state like `this.state =` outside of the constructor, you're not invoking a re-render. use the function `this.setState({ ... })` as this will trigger the lifecycle motions needed – Sterling Archer Feb 26 '18 at 02:22
  • Don't assign to `state` outside of the constructor, use `setState` instead – SrThompson Feb 26 '18 at 02:25
  • Also, minor suggestion: on lines like this `etiqueta_id = this.props.etiqueta.id ;` don't forget the `const` (or `let`) in front, otherwise you'll end up creating a bunch of global variables that might cause issues later. – kingdaro Feb 26 '18 at 02:29
  • @SterlingArcher and at SrThompson thanks for that, makes sense. I changed, but everything looks the same. (Ill update the code) – kilinkis Feb 26 '18 at 02:36
  • @kingdaro thanks, I come from php and sometimes forget to make proper declarations – kilinkis Feb 26 '18 at 02:37

1 Answers1

2

When you need to update the state outside of the constructor, use this.setState, to let React know it needs to do a re-render.

this.setState({
  slider1ActiveSlide: 0,
  slider1Ref: null,
  entries: ENTRIES1,
  isMounted: true
})
kingdaro
  • 11,528
  • 3
  • 34
  • 38
  • perfect! this did the trick! thank you so much! the console.log in example2() keeps going on and on thought, is this behavior normal? – kilinkis Feb 26 '18 at 02:44
  • Not really sure on that one :/ I'd suggest using a normal function instead of a getter anyway, for simplicity's sake – kingdaro Feb 26 '18 at 02:49
  • I'll try that, I'm using the example in their github for now. Thank you so much again! – kilinkis Feb 26 '18 at 02:54
  • @kilinkis `get example()` will be called whenever you access `this.example2`, so it'll fire whenever a re-render is triggered for your `EtiquetaDetail` component. See [this question for details on `get`](https://stackoverflow.com/questions/31999259/what-is-the-get-keyword-before-a-function-in-a-class). – sleighty Feb 26 '18 at 07:16