rcastagna rcastagna - 2 months ago 8
React JSX Question

ReactJS not binding via map to state values

I'm working with an MVC5 project and running into an issue with React not binding an array. I had this working in an MVC Core project, but had to "regress" back to the old structure. Biggest change seemed to be in the controller, changing from JsonResult (Core MVC) to Json (MVC5) for the return type on the ajax call.

Here's the output from Chrome Developer Tools:
(removed due to lack of reputation points)

And, my code for my .jsx file:

var LineItem = React.createClass({
render: function () {
return (
<div className="gridItem">
<div className="lessLineHeight smallFont">
<div className='section group'>
<div className="col span_1_of_2" id={this.props.ordHeaderId}>
<text>{this.props.code}</text>
</div>
<div className='col span_1_of_2 text-right'>
<i className={this.props.apptIconString} aria-hidden='true'></i>
<i className={this.props.highValueIconString}></i>
<i className={this.props.hazmatIconString}></i>
</div>
</div>
<div className='section group'>
<div className='col span_6_of_10'>
<text title='Trading Partner - Client'>{this.props.tradingPartnerName}</text>
</div>
<div className='col span_4_of_10 text-right'>
<text className='overflowElip' title='Account Manager'>{this.props.accountManager}</text>
</div>
</div>
<div className='section group'>
<div className='col span_1_of_2'>
<text title={"Origin: " + this.props.originAddress + "; " + this.props.origContact}>{this.props.originAddress}</text>
</div>
<div className='col span_1_of_2 text-right'>
<text title={"Destination:" + this.props.destinationAddress + "; " + this.props.destContact}>{this.props.destinationCity}</text>
</div>
</div>
<div className='section group'>
<div className='col span_1_of_3'>${this.props.freightValue}</div>
<div className='col span_1_of_3 text-center'>
<a title='Promote Order to Load'>To Load</a>
</div>
<div className='col span_1_of_3 text-right' id={'datePlanned' + this.props.ordHeaderId}>
<text title='Pickup Date'>{this.props.dateCreated}</text>
</div>
</div>
</div>
</div>
);
}
});

var ItemList = React.createClass({
getInitialState: function () {
return { items: [] };
},
loadData: function () {
$.ajax({
url: this.props.url,
dataType: 'json',
success: function (data) {
console.log(data);
this.setState({ items: data });
console.log(this.state.items);
$("#column1").find(".gridItem:odd").css({ "background-color": "#ddd" }).end().find(".gridItem:even").css({ "background-color": "#fff" });
}.bind(this),
error: function (xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidMount: function () {
this.loadData();
/*window.setInterval(this.loadData, this.props.pollInterval);*/
},
render: function () {
if (this.state.items) {
console.log("State has items.");
var itemNodes = this.state.items.map(function (foo) {
return (
<LineItem key={foo.ordHeaderId}
accountManager={foo.accountManager}
apptIconString={foo.apptIconString}
commodityDescription={foo.commodityDescription}
commodityId={foo.commodityId}
dateCreated={foo.dateCreated}
deliveryAppt={foo.deliveryAppt}
destContact={foo.destContact}
destinationAddress={foo.destinationAddress}
destinationAddressName={foo.destinationAddressName}
destinationCity={foo.destinationCity}
earlyDeliveryTime={foo.earlyDeliveryTime}
earlyPickupTime={foo.earlyPickupTime}
equipmentName={foo.equipmentName}
freightValue={foo.freightValue}
handlingUnits={foo.handlingUnits}
hazmatIconString={foo.hazmatIconString}
highValueIconString={foo.highValueIconString}
isHazmat={foo.isHazmat}
isHighValue={foo.isHighValue}
lateDeliveryTime={foo.lateDeliveryTime}
latePickupTime={foo.latePickupTime}
loadId={foo.loadId}
loadNum={foo.loadNum}
loadTmsStatus={foo.loadTmsStatus}
ordHeaderId={foo.ordHeaderId}
ordNum={foo.ordNum}
orderType={foo.orderType}
origContact={foo.originContact}
originAddress={foo.originAddress}
originAddressName={foo.originAddressName}
originationCity={foo.originationCity}
pickupAppt={foo.pickupAppt}
pieces={foo.pieces}
plannedEnd={foo.plannedEnd}
plannedStart={foo.plannedStart}
requiredTemp={foo.requiredTemp}
specialInstructions={foo.specialInstructions}
targetCost={foo.targetCost}
teamId={foo.teamId}
tempControlled={foo.tempControlled}
tradingPartnerNameCNum={foo.tradingPartnerNameCNum}
tradingPartnerName={foo.tradingPartnerNameClient}
transportMode={foo.transportMode}
user3gIdBookedBy={foo.user3gIdBookedBy}
user3gIdCreatedBy={foo.user3gIdCreatedBy}
weight={foo.weight} />
);
});
return (
<div className="itemList">
{itemNodes}
</div>
);
} else {
return null;
}
}
});

ReactDOM.render(
<ItemList url="/DispatchBoard/getColumn1Data" pollInterval={2000} />,
document.getElementById('column1')
);


As you can see from the image, the render: in the loadData function sees the items coming back from the ajax call, and then sets them to state, but when it comes time to map them, it does nothing.

Any ideas on what I'm not seeing?

EDIT

Here's a screen show showing the 'undefined' value(s) in one of the LineItems after failing to map properly. undefined values

EDIT #2

Here's a screenshot showing that the objects are hydrated and not being parsed. object present, not parsed

Answer

After seeing the screenshot you posted in EDIT #2

The issue is you're using different property name when accessing the data from foo while setting the properties on your component

So changing it from

<LineItem key={foo.ordHeaderId}
  accountManager={foo.accountManager}
  apptIconString={foo.apptIconString}

to

<LineItem key={foo.ordHeaderId}
  accountManager={foo.AccountManager}
...

should do the trick

That is use the exact property name from your foo object instead of using camel cased or some other version of it.

Comments