Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to access vairables outside of map function in js and jsx in a React component

var PieceList = React.createClass({

  render: function() {

    var pieces;
    if (this.props.pieces && this.props.onDeletePiece2) {
      var pieces = this.props.pieces.map(function (piece) {
        return (
          <Piece pieceData={piece} onDeletePiece3={this.props.onDeletePiece2} />
        )
      });
    }
    return (
      <div className="piecesTable">
        {pieces}
      </div>
    );  
  }
});

I'm stumped as to how to get this to work. The problem is that {this.props} is not available inside of the map function.

Would a foreach be better here? stumped, pls halp!

like image 723
bignore59 Avatar asked Jun 26 '15 20:06

bignore59


People also ask

Can you use JSX outside of React?

JSX is not a requirement for using React. Using React without JSX is especially convenient when you don't want to set up compilation in your build environment. Each JSX element is just syntactic sugar for calling React. createElement(component, props, ...children) .

How do you get data from array of objects in React JS?

How we will render an Array of Objects? We will use the map function to access each object from the array. The map() method in JavaScript creates an array by calling a specific function on each element present in the parent array. It is a non-mutating method.


2 Answers

map is just a regular JavaScript method (see Array.prototype.map). It can take an argument that sets the context (.map(callback[, thisArg])):

var PieceList = React.createClass({

  render: function() {

    var pieces;
    if (this.props.pieces && this.props.onDeletePiece2) {
      var pieces = this.props.pieces.map(function (piece) {
        return (
          <Piece pieceData={piece} onDeletePiece3={this.props.onDeletePiece2} />
        )
      }, this); // need to add the context
    }
    return (
      <div className="piecesTable">
        {pieces}
      </div>
    );  
  }
});

I would suggest going back and reading about this in JavaScript. When you pass an anonymous function to most methods (like .map, .forEach, etc.), it takes the global context (which is almost always window). If you pass in this as the last argument, since that this is referring to the class you just created with React.createClass, it'll set the correct context.

In other words, the way you were trying to do it was access window.props, which obviously doesn't exist. I'd if you opened your console to debug, you'd see the error Object Window doesn't have the property "props" or something very obfuscated.

like image 178
Josh Beam Avatar answered Oct 08 '22 21:10

Josh Beam


EDIT 2: React 0.14.x

You can now define stateless functional components for components that do not require complex lifecycle event hooks or internal state

const PieceList = ({pieces, onDeletePiece2}) => {
  if (!onDeletePiece2) return;
  return (
    <div className="piecesTable">
      {pieces.map(x => (
        <Pieces pieceData={x} onDeletePiece3={onDeletePiece2}>
      ))}
    </div>
  );
};

EDIT 1: ES6

As ES6 continues to become more prominent, you can also avoid nitpicky context issues by using an ES6 arrow function.

class PieceList extends React.Component {
  renderPiece(piece) {
    return <Piece pieceData={piece} onDeletePiece3={this.props.onDeletePiece2} />;
  }
  render() {
    if (!this.props.onDeletePiece2) return;
    return (
      <div className="piecesTable">
        {this.props.pieces.map(piece => this.renderPiece(piece))}
      <div>
    );
  }
}

To get this to run in most environments, you'd need to "transpile" it using something like babel.js


The quick answer is that you need to bind the proper this to the map callback by passing this as the second arg

this.props.pieces.map(..., this);

This might be a better way to write your component tho

var PieceList = React.createClass({

  renderPiece: function(piece) {
    return <Piece pieceData={piece} onDeletePiece3={this.props.onDeletePiece2} />;
  },

  render: function() {
    if (!this.props.onDeletePiece2) return;
    return (
      <div className="piecesTable">
        {this.props.pieces.map(this.renderPiece, this)}
      </div>
    );
  }
});

Regarding your comment about map

var x = {a: 1, b: 2};

['a', 'b'].map(function(key) {
  // `this` is set to `x`
  // `key` will be `'a'` for the first iteration
  // `key` will be `'b'` for the second iteration
  console.log(this[key]);
}, x); // notice we're passing `x` as the second argument to `map`

Will output

// "1"
// "2"

Notice how the second argument to map can set the context for the function. When you call this inside the function, it will be equal to the second variable that was sent to map.

This is JavaScript basics and you should definitely read up more here

like image 30
Mulan Avatar answered Oct 08 '22 23:10

Mulan