Reputation: 855
So i have an array.map of buttons that cycles through an array of api data. When i click this button, I want to take that specific buttons data, and store it in local storage. I am at a loss on how to do this via the googles. Any ideas?
{this.state.sb_headers.map((header, index) => (
<Link key={index} to={header.title} className="list-group-item list-group-item-action" aria-
current="true" onClick={this.storeUrl}>
<span className='icon-text'>{header.title}</span>
</Link>
))}
So in the storeUrl function, I want to take the data from the link that was clicked and store it. As an example, lets say there are 5 items in the array that are being looped through. each one has a different URL. I want the URL that i click on.
Upvotes: 0
Views: 838
Reputation: 1439
Let's assume that each header item that you are mapping over has a property named "url".
Your onClick for the Link component would call the storeUrl method with the url parameter:
onClick={this.storeUrl(header.url)}
Then, your storeUrl method would look like this:
storeUrl(url) {
return function() {
// do something with url
}
}
This is a closure and the returned function won't be invoked until the link is clicked.
Upvotes: 1
Reputation: 40002
The easiest solution (though not the most performant) is assigning a wrapped function to the event listener.
{this.state.sb_headers.map((header, index) => (
<Link key={index} to={header.title} className="list-group-item list-group-item-action" aria-
current="true" onClick={() => this.storeUrl(header)}>
<span className='icon-text'>{header.title}</span>
</Link>
))}
You can see I created a fat arrow function that invoked storeUrl with header as the parameter. This creates a new function for every Link on every render. Not optimal but it'll do the trick. Another way to write this is as a function that returns a function:
function storeUrl(header) {
return function(e) {
// This is the function that's called on click, it has access
// to header via lexical scope
}
}
{this.state.sb_headers.map((header, index) => (
<Link key={index} to={header.title} className="list-group-item list-group-item-action" aria-
current="true" onClick={this.storeUrl(header)}>
<span className='icon-text'>{header.title}</span>
</Link>
))}
The final option is to attach some data to the button that can be retrieved through the click event.
{this.state.sb_headers.map((header, index) => (
<Link key={index} to={header.title} className="list-group-item list-group-item-action" aria-
current="true" onClick={this.storeUrl} data-index={index}>
<span className='icon-text'>{header.title}</span>
</Link>
))}
// Your storeUrl method will receive e as an event
function storeUrl(e) {
// Get more information about the click
// The value will be a string so the + transforms it back to a number
let index = +e.target.getAttribute('data-index');
let header = this.state.sb_headers[index];
// Whatever you were going to do with header
}
This solution is more performant as it doesn't create a bunch of extra wrapped functions, though the performance is can be negligible depending on the application size.
Upvotes: 2