Purrx
Purrx

Reputation: 63

Dynamic onClick and render in ReactJS

im new to React and I need some help figuring this out!

I have a Json object:

var exampleJson = {
    title: "title",
    blocks: [
        {
            type: "block1",
            items: [{id: "1", count: 1},
                    {id: "2", count: 1},]
        },
        {
            type: "block2",
            items: [{id: "3", count: 1},
                    {id: "4", count: 1},]
        },
]};

I want to get every block in the object and render the data inside each block(including looping through items inside the block) in a div. The div should have a dynamic onClick-event that registers wich block was clicked.

This is what I got:

var BlockListClass = React.createClass({
blockClicked: function() {
    // Here I dont know what block I clicked
},
loopBlocks: function(_data, blockClicked) {
         // loop blocks
        {_data.map(function(object, i){
            var result = <div className="block" key={i}> 
                      {[ 
                         <h2 onClick={blockClicked} key={i}> {object.type} </h2>
                      ]}
                  </div>; 
         // Loop items
         for (var key in object.items) {
              if (object.items.hasOwnProperty(key)) {
               result.props.children.push(<h2 key={key+10}> {object.items[key].id} </h2>);
              }
            }
         return result;
         })}
},
render: function() {
  var _data = exampleJson.blocks;
  var blockClicked = this.blockClicked;
  var renderer = this.loopBlocks(_data,blockClicked);
  return(
    <div className="BlockList">
    {renderer}
    </div>
    );
}

});

And then render BlockListClass like this:

<BlockListClass />

Upvotes: 1

Views: 3284

Answers (2)

deowk
deowk

Reputation: 4318

// you could do something like this

var BlockListClass = React.createClass({
blockClicked: function(e) {
    var id = e.currentTarget.id;
    console.log(id);
},
loopBlocks: function(_data, blockClicked) {
         // loop blocks
        {_data.map(function(object, i){
            var result = <div className="block" key={i}> 
                      {[ 
                         <h2 onClick={blockClicked} id={i} key={i}> {object.type} </h2>
                      ]}
                  </div>; 
         // Loop items
         for (var key in object.items) {
              if (object.items.hasOwnProperty(key)) {
               result.props.children.push(<h2 key={key+10}> {object.items[key].id} </h2>);
              }
            }
         return result;
         })}
},
render: function() {
  var _data = exampleJson.blocks;
  var blockClicked = this.blockClicked;
  var renderer = this.loopBlocks(_data,blockClicked);
  return(
    <div className="BlockList">
    {renderer}
    </div>
    );
}
});

Upvotes: 0

Robert
Robert

Reputation: 1

The question that you asked is essentially, "how do I pass arguments to onClick events on React Elements". This is a common pattern you will have to follow in React. The easiest way to do this, is just to bind the value to the function call. i.e.

<h2 onClick={blockClicked.bind(this, i)} key={i}> {object.type} </h2>

Then your handler would look like the following

blockClicked: function(i) {
    console.log(i);
},

If you still need access to the click event, then you could initially pass in the index value, and return a function to be called when the onClick event is triggered:

<h2 onClick={blockClicked(i)} key={i}> {object.type} </h2>

With a resulting handler:

blockClicked: function(i) {
  return function(e) {
    console.log(i);
    // do what you want with 'e' 
  }
}

Edit: I should also note that my answer is very general. Since your element is nested in a map(function(){...}), binding 'this' will cause an error. You will need to bind it to the correct context. However, I think that is out of the scope of this question. Just wanted to let you know if you run into that issue.

Upvotes: 0

Related Questions