2

I'm currently using Flickr api to make a Simple Image Carousel and facing a problem where my state does not get updated or rendered whenever I click the button.

Here is my index.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import _ from 'lodash';

import Photo from './components/photo';

const urlArr = [];
const apiKey = "API";
const userId = "ID";
const url = `https://api.flickr.com/services/rest/?method=flickr.people.getPublicPhotos&api_key=${apiKey}&user_id=${userId}&format=json&nojsoncallback=1`;

class App extends Component {
  constructor(props) {
    super(props);

    this.state = { urlArr: [] };

    axios.get(url)
    .then((photoData) => {
      _.forEach(photoData.data.photos.photo, (photo) => {
        urlArr.push(`https://farm6.staticflickr.com//${photo.server}//${photo.id}_${photo.secret}_z.jpg`);
      });
      this.setState({ urlArr });
    });
  }

  render() {
    return (
      <div>
        <Photo urls={this.state.urlArr}/>
      </div>
    );
  }
};

ReactDOM.render(<App/>, document.querySelector('.container'));

and here is my photo.js

import React, { Component } from 'react';
import NextButton from './nextButton';
import PrevButton from './prevButton';

class Photo extends Component {
  constructor(props) {
    super(props);

    this.state = { idx: 0 };
    this.nextImg = this.nextImg.bind(this);
  }

  nextImg() {
    this.setState({ idx: this.state.idx++ });
  }

  render() {
    if (this.props.urls.length === 0) {
      return <div>Image Loading...</div>
    }

    console.log(this.state);
    return(
      <div>
        <PrevButton />
        <img src={this.props.urls[this.state.idx]}/>
        <NextButton onClick={this.nextImg}/>
      </div>
    );
  }
}

export default Photo;

and my nextButton.js (same as prevButton.js)

import React from 'react';

const NextButton = () =>{
  return (
    <div>
      <button>next</button>
    </div>
  );
};

export default NextButton;

Since I'm fairly new to React, I'm not quite sure why my this.state.idx is not getting updated when I click on the next button (Seems to me that it is not even firing nextImg function either). If anyone can give me a help or advice, that would really appreciated.

Thanks in advance!!

1
  • You should check if nextImg get fired when you click on the button
    – kkkkkkk
    Commented Nov 28, 2016 at 8:54

2 Answers 2

1

Update your NextButton. Use the event within your presentational component.

<NextButton next={this.nextImg}/>

And the NextButton component should looks like this.

import React from 'react';
 const NextButton = (props) =>{
 return (<div>
    <button onClick={props.next}>next</button>
  </div>
 );
};
3
  • Sorry, it does not work..and I thought this.nextImg = this.nextImg.bind(this) in my constructor is taking care of that..not sure tho..
    – ckim16
    Commented Nov 28, 2016 at 8:53
  • it still does not update my state. However, whenever I click 'next', it logs props as an empty object.
    – ckim16
    Commented Nov 28, 2016 at 9:02
  • See the above answer, this.setState({ urlArr }); is not being called in the right context in your main Component constructor. Commented Nov 28, 2016 at 9:05
1

The problem lies with this piece of code:

axios.get(url)
.then((photoData) => {
  _.forEach(photoData.data.photos.photo, (photo) => {
    urlArr.push(`https://farm6.staticflickr.com//${photo.server}//${photo.id}_${photo.secret}_z.jpg`);
  });
  this.setState({ urlArr });
});

this refers to the axios.get callback scope and not the Component. You can define another variable called self or something that makes more sense to you and call self.setState().

See this question for a similar problem: Javascript "this" scope

Not the answer you're looking for? Browse other questions tagged or ask your own question.