ReactJS how to loop through dynamically named refs - reactjs

I'm looking at a line of code that has dynamically named refs for an input, where 'item' is an incrementing value starting at zero.
"input type="text" ref={'name'+item} defaultValue={item} />"
How would I loop through these dynamic refs to scrape out the values? I tried this with no luck. It tells me object undefined. (the length of inputs will equate to the number of added elements)
var arr = this.state.inputs;
var arrayLength = arr.length;
for (var i = 0; i < arrayLength; i++) {
var c = this.refs.name + i.value
alert(c);
}
Though, this DOES work, but its dynamic, so I need to loop through it, not hard code it:
alert(this.refs.name0.value);
alert(this.refs.name1.value);
alert(this.refs.name2.value);

I believe you need to get the DOM objects for the inputs, not just the refs (at least that has been my experience):
import ReactDOM from 'react-dom';
const values = {};
Object.keys(this.refs)
.filter(key => key.substr(0,4) === 'name')
.forEach(key => {
values[key] = ReactDOM.findDOMNode(this.refs[key])).value || null;
});
Good luck!

Related

For Loop alternative with Lodash ( React Native )

I was trying to itertate an array and access description
Array
i'm itertaing via regular for loop like this
for (var index = 0; index <components.length; index++) {
const msgs = components[index].messages;
for(var value = 0; value < msgs.length; value ++ ){
console.log(msgs[value].description);
}
}
Please let me know how we can simplify it by using loadash methods in react native.
here it is using lodash
import {forEach} from 'lodash';
forEach(components,(component,index)=>{
const msgs = component.messages;
forEach(msgs,(msg,value)=>{
console.log(msg.description);
});
});

How to fetch objects of array one by one with for loop in react native

I've written for loop to fetch objects from array one by one, but the result fetched all of objects from loop and repeated those in one string.
Here is my code:
state = {
b: ["A","B","C","D","E","F","G","H","I"]
}
b = () => {
let d = [];
for (var i =0; i<=this.state.b.length - 1; i++) {
d.push(this.state.b[i])
}
return d;
};
I'm beginner in react native, how can I change this code to show object arrays like a list
You can use ListView directly like this :
<ListView
dataSource={this.state.b}
renderRow={(rowData) => <Text>{rowData}</Text>}
/>

Iterating through HTMLcollection in React,js

I am having trouble iterating through and HTMLCollection in a React.js component. I have the following function:
shuffleLists = () => {
var elems = document.getElementsByTagName("ul");
console.log(elems)
for (let item of elems) {
console.log(item);
}
}
console.log(elems) prints out an HTMLCollection of ul elements as expected. But the for loop after it doesn't print anything in the console, when I would expect to see each ul element printed in the console. What am I doing wrong?
Edit for clarity:
The key issue here is that the line console.log(item) inside the loop does not output anything into the console in chrome dev tools, and the same applies to other various loop syntaxes as discussed in the answers and comments below.
I also have noticed that there is different lengths being logged from console.log(elems) between different browsers. In chrome I see HTMLCollection[] length: 10 ...
But in Firefox I see
HTMLCollection {length 0} ...
The item in your for loop is actually the key (array index). You need to get the particular element from the elems array by using the syntax elems[item].
Refactoring your code (and changing item to key, just for clarity):
shuffleLists = () => {
var elems = document.getElementsByTagName("ul");
console.log(elems);
for (let key of elems) {
console.log(elems[key]);
}
}
UPDATE: because result of getElementsByTagName() is a NodeList
shuffleLists = () => {
var elems = document.getElementsByTagName("ul");
console.log(elems);
elems.forEach(function(val) {
console.log(val);
})
}
From the MDN Web Docs
Although NodeList is not an Array, it is possible to iterate over it
with forEach(). It can also be converted to a real Array using
Array.from().
However, some older browsers have not implemented NodeList.forEach()
nor Array.from(). This can be circumvented by using
Array.prototype.forEach().
As per the updated requirement of the OP
shuffleLists = () => {
var ulElems = document.getElementsByTagName("ul");
console.log(ulElems);
for(i = 0; i < ulElems.length; i++) {
var liElems = ulElems[i].getElementsByTagName("li");
for(j = 0; j < liElems.length; j++) {
console.log(liElems[j].innerHTML);
}
}
}
document.getElementsByTagName will return an array of elements, in your case array of elements in the page, so you need to have something like the following if you want to have the first ul
shuffleLists = () => {
var elems = document.getElementsByTagName("ul");
console.log(elems)
for (let idx of elems) {
console.log(elems[idx]);
}
}
I would suggest to use document.getElementById() to be more precise about your selected elements
I figured out my problem was that I was calling the shuffleLists function from the parent component in React, prior to the ul and li elements I wanted to iterate through being rendered in the sub-component. The console output for the elems var was confusing as it showed all the lists and list items inside the HTMLCollection.
When I moved the shuffleLists function to the sub-component and called it inside componentDidMount I was able to loop through and console out all the list items as desired.

TypeScript and React JS Access The DOM Element

I have this code here, it says, elements[i].style does not exist, any idea why?
let elements = document.getElementsByClassName("contentHeaderTitleField");
for (var i = 0, length = elements.length; i < length; i++) {
if (elements[i].textContent == '') {
elements[i].style
}
}
By default, method getElementsByClassName returns HTMLCollectionOf<Element>,
and Element interface doesn't have 'style' property, so you should, for example, cast the return type to collection of HTML elements, like this:
let elements = document.getElementsByClassName("contentHeaderTitleField") as HTMLCollectionOf<HTMLElement>

Testing Angular Filter That Returns An Array with Jasmine

So, I'm having issues testing an angular filter that takes an array that has previously been sorted by a group property. It uses a flag property to indicate that the item is the first observation of that group, and then false for subsequent observations.
I'm doing this to have a category header in the UI with an ng-repeat directive.
When I test the filter, the output does not return the array with the flags unless I create new objects for the return array. This is a problem, because it causes an infinite loop when running in a webpage. The code works in the webpage when it just adds a flag property to the input object.
Is there some additional step I should be taking to simulate how angular handles filters so that it outputs the proper array?
This is what my test looks like right now.
describe('IsDifferentGroup', function() {
var list, itemOne, itemTwo, itemThree;
beforeEach(module("App.Filters"));
beforeEach(function () {
list = [];
itemOne = new ListItem();
itemTwo = new ListItem();
itemThree = new ListItem();
itemOne.group = "A";
itemTwo.group = "B";
itemThree.group = "C";
list.push(itemOne);
list.push(itemOne);
list.push(itemOne);
list.push(itemOne);
list.push(itemTwo);
list.push(itemThree);
list.push(itemThree);
list.push(itemThree);
list.push(itemThree);
list.push(itemThree);
});
it('should flag the items true that appear first on the list.', (inject(function (isDifferentGroupFilter) {
expect(list.length).toBe(10);
var result = isDifferentGroupFilter(list);
expect(result[0].isDifferentGroup).toBeTruthy();
expect(result[1].isDifferentGroup).toBeFalsy();
expect(result[4].isDifferentGroup).toBeTruthy();
expect(result[5].isDifferentGroup).toBeTruthy();
expect(result[6].isDifferentGroup).toBeFalsy();
expect(result[9].isDifferentGroup).toBeFalsy();
})));
});
And here is something like the code with the filter:
var IsDifferentGroup = (function () {
function IsDifferentGroup() {
return (function (list) {
var arrayToReturn = [];
var lastGroup = null;
for (var i = 0; i < list.length; i++) {
if (list[i].group != lastGroup) {
list[i].isDifferentGroup = true;
lastAisle = list[i].group;
} else {
list[i].isDifferentGroup = false;
}
arrayToReturn.push(list[i]);
}
return arrayToReturn;
});
}
return IsDifferentGroup;
})();
Thanks!
I figured out my issue.
When I was passing the items into the list, I just pushed a pointer to an item multiple times. I was not passing in unique objects so the flag was being overridden by the following flag in the array(I think). So, I just newed up 10 unique objects using a loop, pushed them into the array and ran it through the filter. And it worked.
I'm not entirely sure my analysis is correct about the override, because itemTwo was not being flagged as unique when it was the only itemTwo in the array. But the test is working as I would expect now so I'm going to stop investigating the issue.

Resources