I created a web page that dynamically loads its contents using React.js. I extract an array of objects from a REST api call and then load them into a table. The problem is that assigning onClick from array.map does not call the assigned function.
I believe this is a [ this ] problem , but I'm not sure how to solve it. [ this ] in array.map is not the same [ this ] outside array.map, as shown in console.log.
I created two standalone html files for demonstration. The first contains a statically created object that correctly calls the onClick function:
https://jsfiddle.net/m1vugyd9/
The second attempt to dynamically load from an array of objects and does not work:
https://jsfiddle.net/avmbdxte/
I have no idea how long these links remain active, so if they don't work, I also included the actual html below. The difference is somewhat emphasized by the comments.
Static - works:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<style>
table {
text-align: center;
}
</style>
</head>
<body>
<div id="reactDiv"></div>
<script src="https://fb.me/react-0.14.3.min.js"></script>
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/jsx">
var FMap = React.createClass({
render: function() {
return (
<tr>
<td>{this.props.sTable}</td>
<td>{this.props.sField}</td>
<td>{this.props.dTable}</td>
<td>{this.props.dField}</td>
<td><a href="#" onClick={this.props.mapCountClick}>{this.props.mapCount}</a></td>
</tr>
);
}
});
var Main = React.createClass({
getInitialState: function () {
return { mapData: [] };
},
editMaps: function() {
alert("Clicked on map editor");
},
render: function () {
var maps = [
{
mapID: 1,
sourceT: "sT1",
sourceF: "sF1",
destT: "dT1",
destF: "dF1",
mapCount: 6
},
{
mapID: 2,
sourceT: "sT1",
sourceF: "sF2",
destT: "dT1",
destF: "dF2",
mapCount: 2
}
];
var fMaps =
<FMap key="1"
sTable="sT1"
sField="sF1"
dTable="dT1"
dField="dF1"
mapCount="6"
mapCountClick={this.editMaps} />;
// end of difference
/////////////////////////////////////////////////////
return (
<table width="100%">
<thead>
<tr>
<th>SourceT</th>
<th>SourceF</th>
<th>DestT</th>
<th>DestF</th>
<th>MapCount</th>
</tr>
</thead>
<tbody>
{fMaps}
</tbody>
</table>
);
}
});
React.render(<Main />, document.getElementById("reactDiv"));
</script>
</body>
</html>
Dynamic - does not work:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<style>
table {
text-align: center;
}
</style>
</head>
<body>
<div id="reactDiv"></div>
<script src="https://fb.me/react-0.14.3.min.js"></script>
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/jsx">
var FMap = React.createClass({
render: function() {
return (
<tr>
<td>{this.props.sTable}</td>
<td>{this.props.sField}</td>
<td>{this.props.dTable}</td>
<td>{this.props.dField}</td>
<td><a href="#" onClick={this.props.mapCountClick}>{this.props.mapCount}</a></td>
</tr>
);
}
});
var Main = React.createClass({
getInitialState: function () {
return { mapData: [] };
},
editMaps: function() {
alert("Clicked on map editor");
},
render: function () {
var maps = [
{
mapID: 1,
sourceT: "sT1",
sourceF: "sF1",
destT: "dT1",
destF: "dF1",
mapCount: 6
},
{
mapID: 2,
sourceT: "sT1",
sourceF: "sF2",
destT: "dT1",
destF: "dF2",
mapCount: 2
}
];
var fMaps = maps.map(function (map) {
var component = this;
return (
<FMap key={map.mapID}
sTable={map.sourceT}
sField={map.sourceF}
dTable={map.destT}
dField={map.destF}
mapCount={map.mapCount}
mapCountClick={this.editMaps} />
);
});
// end
/////////////////////////////////////////////////////
return (
<table width="100%">
<thead>
<tr>
<th>SourceT</th>
<th>SourceF</th>
<th>DestT</th>
<th>DestF</th>
<th>MapCount</th>
</tr>
</thead>
<tbody>
{fMaps}
</tbody>
</table>
);
}
});
React.render(<Main />, document.getElementById("reactDiv"));
</script>
</body>
</html>
Working example (thanks pvg!):
https://jsfiddle.net/qLp9uuq3/
Another working example (thanks to Matthew Herbst!):
https://jsfiddle.net/09n6xss2/