0

This is a React/Redux app. I have two components. One nested in the other.

<UserReview>
  <UserReviewItem>
</UserReview>

I am working with two APIs. I call one API to get a 'movieId', I use the 'movieId' to call a second API to retrieve an image. I am mapping over an array, but it seems like it is only returning the last element's movieId.

The wrapping component:

    class UserReview extends Component {
      componentDidMount() {
        this.props.fetchAllReviews();
      }

      render() {
        const allReviews = this.props.reviews.slice(-2).map((review, i) => {
          return (
            <UserReviewItem
              username={review.username}
              text={review.text}
              key={review._id}
              movieId={review.movieId}
            />
          )
        });
const mapStateToProps = state => ({
  reviews: state.movies.reviews
})

Child Component:

    class UserReviewItem extends Component {
        componentDidMount() {
            **this.props.fetchImage(this.props.movieId)**
        }
        render() {
            return (
                <div key={this.props.key}>
                    <img
                        src={`https://image.tmdb.org/t/p/original/${this.props.img}`}
                    />
                    <div>
                        <h4>{this.props.username}</h4>
                        <p>{this.props.text}</p>
                    </div>
                </div>
            );
const mapStateToProps = state => ({
    img: state.movies.img
})

I want a different image for every item in the array but I am getting the same image even though the usernames and texts are different.

A solution I tried but got the same result:

class UserReview extends Component {
  componentDidMount() {
    this.props.fetchAllReviews();
  }

  render() {
    const allReviews = this.props.reviews.slice(-2).map((review, i) => {
      return (
        <UserReviewItem
          username={review.username}
          text={review.text}
          key={review._id}
 -------> movieId={this.props.reviews[i].movieId} <--------
        />
      )
    });

const mapStateToProps = state => ({
  reviews: state.movies.reviews
})
16
  • 1
    Your UserReviewItem Component will be mounted only once when its loaded initially. THe problem is why are you trying to make n+1 queries to your backend if you can return the image of the user along with the fetchAllReviews API. like user_image : 'some_image_URL'. Why cant you do that? Commented Jan 13, 2020 at 7:07
  • Also Where are you assigning image src? Which in your case should be prop sent in UserReviewItem: img Commented Jan 13, 2020 at 7:16
  • @Mobeen he is trying to fetchImage from the moveId that is sent in the props in COmponentDidMount which wont work iteratively. He is using this.props.img in the Image url if you check. Commented Jan 13, 2020 at 7:18
  • @Lonewolf But OP isnt setting that value anywhere Commented Jan 13, 2020 at 7:19
  • As far as I know, componentDidMount in the child will call before the parent, do your api really calling with the right sequence o.o? fetchImage should call before fetchAllReviews, please correct me if I'm wrong.. Commented Jan 13, 2020 at 7:26

2 Answers 2

0

You can try this way:

class UserReview extends Component {
      componentDidMount() {
        this.props.fetchAllReviews();
      }
      
      renderItems(){
      const { reviews } = this.props
      if (!reviews) return []
      return reviews.map(review => <UserReviewItem
              username={review.username}
              text={review.text}
              key={review._id}
              movieId={review.movieId}
            />)
      }

     

      render() {        
          return (          
            this.props.reviews
             ? <div>{this.renderItems()}</div>
             : <p>Loading...</p>
          )
        };

    const mapStateToProps = state => ({
      reviews: state.movies.reviews
    })
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

basically in the renderItems function you destructure the props, get the reviews and map them. In your render function you set a loader if the views are not ready yet (you can use a loading prop if you are setting that up in your store), or call the list if the reviews are already fetched and ready.

Sign up to request clarification or add additional context in comments.

2 Comments

It's the same result. All 3 components display the same images b/c they all end up with the same movieId. Here is what is happening... 1) fetchAllReviews is called and retrieves movieId 2) movieId is used as a parameter in the fetchImage function to make a call to another API where the images are 3) As a result, a url path is returned '/VsrImTfWnDjZ.jpg' 4) The 3 components that should be getting DIFFERENT images end up getting the same image
ok so, all the IDs are correct, the URLs returned for each link are correct, and the image files are all correct? right? Did you try to copy and paste in another browser tab each single URL you get from the api and see if the images are displayed correctly? May be a cache problem if you previously stored a "placeholder image"?
0

I found the answer. Because the second call depends on information from the first call I have to chain the calls using .then()

using a fetch inside another fetch in javascript

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.