3

I am trying to set a video in my app as "Featured" when a user clicks on an item. I have an action creator that does a simple console.log() when called, and for testing I call it w/ componentDidMount(), and it works fine. I have a separate component for the VideoItem, and I'm trying to pass down the action creator, but I get an error: TypeError: Cannot read property 'props' of undefined. I tried to add .bind(this) to the end of the action I was passing down, but it didn't make a difference.

If the action creator works when I call it at componentDidMount, why can't I pass it to the child component? Here's my Video and VideoItem component:

// Video.js


import React, { Component } from 'react'
import VideoItem from './VideoItem'
class Videos extends Component {
  componentDidMount() {
      this.props.actions.getVideos()
      // This function works, but getting error
      // when passing to VideoItem component
      this.props.actions.setFeaturedVideo()
  }
  constructor(props) {
      super(props);
  }
  render() {
    if(this.props.videos.length == 0){
      return <p>Loading....</p>
    }
    return (
        <div className="container">
          <ul className="row">
              {this.props.videos.map(function(result) {
                return (
                    <VideoItem
                    key={result.position}
                    setFeaturedVideo={this.props.setFeaturedVideo}
                    video={result}

                    />
                )
              })}
          </ul>
        </div>
    )
  }
}

export default Videos


// VideoItem.js

import React, { Component } from 'react'
class VideoItem extends Component {
  constructor(props) {
      super(props);
  }
  render() {
    return (
      <li className="col m6" onClick={this.props.setFeaturedVideo()}>
          {this.props.video.title}
      </li>

    )
  }
}
export default VideoItem
Mike
  • 2,633
  • 6
  • 31
  • 41

2 Answers2

5

Missed that this inside a map function. Since you are using map, the "this" belongs to the map function. You need to assign this to a variable before the map function and use that instead.

render() {
    var _that = this;
    if(this.props.videos.length == 0){
      return <p>Loading....</p>
    }
return (
    <div className="container">
      <ul className="row">
          {this.props.videos.map(function(result) {
            return (
                <VideoIte
                key={result.position}
                setFeaturedVideo={_that.props.actions.setFeaturedVideo}
                video={result}

                />
            )
          })}
      </ul>
    </div>
)

}

  • Thanks for the quick reply Norm, I'm still getting the `Videos.js:25 Uncaught TypeError: Cannot read property 'props' of undefined` error when I made that change – Mike Mar 27 '16 at 20:28
  • 1
    I have updated my answer. I missed the fact that you were inside a map function. You need to map "this" to a variable outside of the return, so that you can access it in the map function. – Norm Crandall Mar 27 '16 at 20:35
  • 3
    Norm called out what I picked up on as well and that should be what it was. Just an aside, it looks like you're using ES6. You could destructure your props so that you don't have to do something like `_that`. Instead, you could just have `const {actions, videos} = this.props` at the top of the render method. Then, wherever you've used `this.props.*`, instead just call the thing directly. For example, `videos.map(result => – marcacyr Mar 27 '16 at 21:17
  • 3
    Another additional note - since you're using Redux (I'm assuming based on the actions), instead of having the check for `videos.length === 0`, you could have `isLoading` as part of the state - then when things are loaded, you dispatch an action to update `isLoading` from true to false and have things re-flow accordingly. – marcacyr Mar 27 '16 at 21:20
0

I noticed that to the VideoItem Component you have the code passing the function like so

<VideoItem
  key={result.position}
  setFeaturedVideo={this.props.setFeaturedVideo}
  video={result}
/>

But in your componentDidMount you call this.props.actions.setFeatureVideo()

So to me you are not passing the function down as props since you are trying to get it from this.props instead of this.props.actions

natac
  • 342
  • 2
  • 9