Reputation: 1378
hi guys I'm trying to extract data from this:
1) […]
0: {…}
__v: 0
_id: "5ba96b8ebffd923734090df4"
formID: "5ba96b83bffd923734090df0"
inputArr: Array(3) [ "value1", "value2", "value3" ]
labelArr: Array(3) [ "label1", "label2", "label3" ]
<prototype>: Object { … }
length: 1
<prototype>: Array []
I need to get to the array inside the data, which is this.state.inputData (what you see above is the content),
I tried
const labels = inputDataArr[0].labelArr.map((r, index) => {
return (
<tr key={index}>
<th>{index}</th>
<th>{r[index]}</th>
</tr>
);
but I get item undefined, anybody knows why?
EDIT : additional problem rendering :
renderData(i) {
const { inputDataArr } = this.state;
return (
!!inputDataArr.length &&
inputDataArr[i].inputArr.map((input, index) => (
<th key={index}>{input}</th>
))
);
}
countLength() {
const { inputDataArr } = this.state;
return !!inputDataArr.length && inputDataArr[0].inputArr.length;
}
runThrough() {
for (let i = 0; i < this.countLength; i++) return this.renderData(i);
}
render() {
const data = this.runThrough();
return (
<div className="app">
<table>
<tr>{this.renderLabels()}</tr>
{data}
</table>
</div>
);
}
}
Upvotes: 0
Views: 88
Reputation: 17638
Given the same example from your other question. Not quite sure this suits you as it is, maybe you need to change and think about it a little bit.
class App extends React.Component {
state = {
inputDataArr: [
{
formID: "3",
inputArr: [ "value1", "value2" ],
labelArr: [ "label1", "label2" ],
},
{
formID: "3",
inputArr: [ "value3", "value4" ],
labelArr: [ "label3", "label4" ],
},
],
}
renderLabels() {
const { inputDataArr } = this.state;
return !!inputDataArr.length && inputDataArr[ 0 ].labelArr.map( ( label, index ) =>
( <tr key={label}>
<th>{index}</th>
<th>{label}</th>
</tr> ) );
}
render() {
return (
<div>
<table>
{this.renderLabels()}
</table>
</div>
);
}
}
ReactDOM.render( <App />, document.getElementById( "root" ) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Update after comments
After learning that you are getting the data via an async operation, I've added a small condition to the renderLabels
method. Now it looks for if the array's length returns true
:
return !!inputDataArr.length && inputDataArr[ 0 ]
This is a mix of logical operators and React's rendering logic. Why I use !!inputDataArr.length
instead of inputDataArr.length
?
Normally, in logical operators, if the first condition is 0
then it does not pass the second part.
const num = 0;
num && console.log( "passed the second part" );
As you can see it never passes the second part. This is because 0
means false
here.
React ignores rendering if a value is undefined
or false
or null
. But it renders if a value is 0
:)
Let's see:
class App extends React.Component {
state = {
num: 0,
};
render() {
return (
<div>
{this.state.num && <p>Render me</p>}
</div>
);
}
}
ReactDOM.render( <App />, document.getElementById( "root" ) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
This is similar to your situation. In the first render array's length is 0
. So, if we use this:
return inputDataArr.length && inputDataArr[ 0 ]
it renders a 0
. What we want here is ignore the rendering. So if we use logical NOT operator twice we get a false
here and React ignores rendering. Why we get false
?
Since 0
means false
, !!false
again evaluated to false
. Then, React ignores rendering and we are safe from the error that you provided in your question.
When the data lands your app, in the second render this time array's length is greater than 0
, let's say 2
. !!2
evaluates to true
then React renders the second part of the condition, your label array.
You can write your condition like this if you want:
renderLabels() {
const { inputDataArr } = this.state;
if (inputDataArr.length > 1) {
return inputDataArr[0].labelArr.map((label, index) => (
<tr key={label}>
<th>{index}</th>
<th>{label}</th>
</tr>
));
}
}
Upvotes: 1