I have created a webpage that dynamically loads its content with React.js. I'm retrieving an array of objects from a REST api call, and then feeding them into a table. The issue I have is that the onClick assignment from within the array.map doesn't trigger the assigned function.
I believe this is a [this] context issue, but I'm not sure how to resolve it. The [this] in the array.map is not the same [this] outside of the array.map as demonstrated by console.log.
I have created two standalone html files for demonstration. The first contains a statically created object which is calling the onClick function correctly:
https://jsfiddle.net/m1vugyd9/
The second attempts to dynamically load from an array of objects, and does not work:
https://jsfiddle.net/avmbdxte/
I have no idea how long those links stay active for, so if they don't work, I've also included the actual html below. The difference is somewhat highlighted with 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
}
];
/////////////////////////////////////////////////////
// this is the static part that's different from the dynamic part
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 - doesn't 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
}
];
/////////////////////////////////////////////////////
// this is the part that doesn't work
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 Matthew Herbst!):
thisto some other variable outside of the function def and use that inside the function instead. the behaviour ofthisis special, everything else behaves as expected.