lost9123193
lost9123193

Reputation: 11030

React Props is Not Defined

I'm having trouble understanding why my props.updateBuilding is not working.

The following works when the prop is within the render method

class Buildings extends Component {
  constructor(props) {
      super(props);
  }

  componentWillMount() {
    this.props.fetchBuildings();
  }

  renderBuildings(building) {
    return (
      <div>
          <p> {building.name}</p>
      </div>
    );
  }


  render() {
    return (
      <div> 
        {this.props.buildings.map(this.renderBuildings)}
        <button type="button" className="btn btn-success" onClick={this.props.updateBuilding.bind(this, 1)}>Edit</button>
      </div>
    );
  }
}

function mapStateToProps(state) {
  return { buildings: state.buildings.all };
}
function mapDispatchToProps(dispatch){
  return bindActionCreators({ fetchBuildings, updateBuilding}, dispatch);
}

But when I put this.props.updateBuilding to the renderBuildings method like below...

  renderBuildings(building) {
    return (
      <div>
          <p> {building.name}</p>
          <button type="button" className="btn btn-success" onClick={this.props.updateBuilding.bind(this, building.id)}>Edit</button>
      </div>
    );
  }

I get the error:

Cannot read property 'props' of undefined

It seems that the prop updateBuildings cannot be read when it is inside the renderBuildings method and I'm not sure what is causing this.

Upvotes: 20

Views: 106078

Answers (7)

Sterling Diaz
Sterling Diaz

Reputation: 3875

I was just missing the this keyword this.props.buildings

Upvotes: 0

hvl_52
hvl_52

Reputation: 51

I also had some problems using props with my functional components while doing the todo-tutorial. When you use functional components instead of class components, you'll have to do an import from the node-modules if you want to use props. Put this line at the top of your file:

import props from 'prop-types';

Then, when you'll want to use props in your functional component, you'll first need to pass the keyword as a parameter of this function. After that, you'll be allowed to use it like you would have in a class component but without using the keyword "this" :

function Todos(props) {
  console.log(props.todos);
  return (
    <div className="Todos">
        <h2>This is the Todos component</h2>
    </div>
  );
}

Upvotes: 5

SeeStephSay
SeeStephSay

Reputation: 21

Binding inline isn't recommended anymore. Now, you can remove the constructor function altogether, and instead of declaring a method on the component, you can declare a property, and set it to an arrow function. This will bind properties to the instance.

Special shoutout to WES BOS for teaching that to me just yesterday in his React for Beginners course! :D Super pumped to actually have something to contribute to Stack Overflow!

renderBuildings = (buildings) => {
//this keyword is now available for use here
}

Upvotes: 2

Hemadri Dasari
Hemadri Dasari

Reputation: 33974

You are not recommended to bind the function directly in render or anywhere else in the component except in constructor. Because for every function binding a new function/object will be created in webpack bundle js file hence the bundle size will grow. Your component will re-render for many reasons like when you do setState, new props received, when you do this.forceUpdate() etc. So if you directly bind your function in render it will always create a new function. Instead do function binding always in constructor and call the reference wherever required. In this way it creates new function only once because constructor gets called only once per component.

Bind them in constructor and use the reference like

constructor(props){
    super(props);
    this.renderBuildings = this.renderBuildings.bind(this);
}

this.props.buildings.map(this.renderBuildings)

Upvotes: 1

spencer.sm
spencer.sm

Reputation: 20528

In my case, I forgot to add props as an argument to the constructor.

constructor(props) {
  super(props);
}

Upvotes: 32

CXNAJ
CXNAJ

Reputation: 43

try:

this.props.buildings.map(this.renderBuildings.bind(this))

Upvotes: 2

PhilVarg
PhilVarg

Reputation: 4811

you're miss-reading this error. props is not undefined, what is calling props is undefined, which is the this keyword. you can manually set the context of the map function by passing in a second parameter

this.props.buildings.map(this.renderBuildings, this)

or bind it inline

this.props.buildings.map(this.renderBuildings.bind(this))

Upvotes: 21

Related Questions