1

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 />

2 Answers 2

0

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.

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

Comments

0

// 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>
    );
}
});

3 Comments

Hi! Thank you for your time. However: var id = e.target.id; console.log(id); Both are undefined @deolectrix
did you add id={i} to your <h2>?
you should use bind after map function

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.