Object with similar attribute names loop, React - reactjs

I have object with attributes like tabletA, tabletB, tabletC, containing allways string.
The same object contains other attributes as well, like company, phone.
My goal is to look at attributes in one line, and display only tablet attributes, where are strings, with values.
So I imagine code to look like something like this:
{referenceTexts.[tablet].length > 0 && (
<div>
referenceTexts.[tablet]
</div>
)}

{Object.entries(referenceTexts)
.filter(([key, val]) => key.startsWith('tablet') && val.length > 0)
.map(([_, val]) => (
<div>{val}</div>
))}

const tabletValues = Object.keys(referenceTexts)
// get keys that start with "tablet"
.filter(key => key.startsWith('tablet'))
// get their values
.map(key => referenceTexts[key])
// get only values that are not empty
.filter(value => (value || '').length > 0);
Then
{tabletValues.map(value => <div>{value}</div>)}
Note that the order of the values is undefined so you might want to add some kind of sorting.

hopefully I got you. You want something like this :
{Object.keys(referenceTexts).map((key) => {
if (key.substr(0, 6) === "tablet") {
return <h1>{referenceTexts[key]}</h1>;
}
})}

Related

Cannot remove duplicates

I follow this question to achieve the result Remove duplicate values from JS array. Also, I read a lot of stuff like https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set, but unfortunately, values are still duplicated
.map((devicedetails, index) => {
return (
<option key={index} value={[...new Set(devicedetails.groupName)]}>
{[...new Set(devicedetails.groupName)]}
</option>
);
});
Note: I thought it's clear but **devicedetails ** consists of JSON with multiple values, not just one
Result:
Updated:
before return: var list = [];
filteredList.map((devicedetails, index) => {
list.push(devicedetails.groupName);
if (list.length === index + 1) {
var data = [...new Set(list)];
data.forEach((element) => {
return <option value={element}>{element}/option>;
});
}
})
But in this case, is returning nothing in option but it's working I check via console.log(element)
You need to remove duplicates of the whole array and then map over the version with duplicates removed.
[...new Set(myArray)].map((devicedetails, index) => (
<option key={index} value={devicedetails.groupName}>
{devicedetails.groupName}
</option>
));
Instead of looping over devicedetails, outside of the return, create a modified array using the spread syntax and set it as a new variable. Then loop over that instead.
e.g.
const array = ['test', 'testing', 'test', 'test1234', 'testing']
const updatedArray = [...new Set(array)]
console.log(updatedArray)

Filter table with select options (check if column is number or null) in React

I am new at React and I am stuck.
I have a table with data from database. I want to filter that table with a select dropdown. I have mulitple "select-fields" that works fine, because the value in the dropdown matches the exact value in database. But now I just want to check if the column value is null or a number.
In my select options I just want three options (see left picture):
All (Show all result. It is working)
Missing number(is null in Database. Not working)
Has number(Not working)
So the value in the table column (see right picture) I want to filter is either a number or null.
Here is my code so far:
const [filteredData, setFilteredData] = useState([]);
//Column in table:
{
Header: () => (<div>TableHead</div>),
accessor: "accessorToDatabase",
Cell: (props) => { return <div>{props?.cell?.value}</div> }
}
// The select dropdown and the table
<Col>
<Label>Select Dropbox</Label>
<Input type="select" onChange={handleChange('id', 'description')}>
<option>All</option>
<option value="false">Missing number</option>
<option value="true">Has number</option>
</Input>
</Col>
<Table columns={columns} data={filteredData} HandleRowData={HandleRowData} />
//The filter functions
const handleChange = name => ({ target: { value } }) => {
filter[name] = (value === 'All') ? null : value
if (checkProperties(filter)) {
var filtered = state
}
else {
var filtered = handleFilter(state, filter)
}
setFilteredData(filtered)
}
const handleFilter = (arr: Object[], filters: Object) => {
const filterKeys = Object.keys(filters)
return arr.filter(eachObj => {
return filterKeys.every(eachKey => {
if (!filters[eachKey] || !filters[eachKey].length) {
return true
}
})
})
}
I have tried with something like this, for looping through all values in the column, but without no success:
state.map(x=>((
x.id> 0 ? x.id : null)))
.map is used to transform one array of values/objects to another array with the same length but with transformed values/objects. What you want to use is .filter, which removes elements from an array but maintain the element structure.
To keep the ones that does not have an id:
array.filter(x => !x.id)
To keep the ones that has an id that is a number:
array.filter(x => !isNaN(x.id))
A simple Array.prototype.filter should do the trick:
//removes all entries with an id of `0 || null || undefined`
state.filter(entry=>!!entry.id)
//removes all entries with an id of `null || undefined` but keeps the 0
state.filter(entry=>!!entry.id || entry.id === 0)
I would not recommend using isNan: as it internally tries to parse strings to check if they are numbers you might end up with some unexpected behaviors. It also goes wild with booleans, null and undefined.
See this link for more info:
https://www.w3schools.com/jsref/jsref_isnan.asp
EDIT
Rereading your question it looks like you want
all items
items with an ID of type number
items that are not numbers
Here is how you could implement that
const [items,setItems]= useState(someItems)
const [filter, setFilter]=useState('all')
function handleChange(e){
setFilter(e.target.value)
}
const filteredItems = items.filter(item=>{
if(filter === 'number')
return typeof items === 'number'
if(filter === 'no-number')
return typeof item !== 'number'
return true
})
return (
<React.Fragment>
<select onChange={handleChange}>
<option value='all'>All</option>
<option value='no-number'>Missing number</option>
<option value="number">Has number</option>
</select>
<Table columns={columns} data={filteredData} HandleRowData={HandleRowData} />
</React.Fragment>
)
Change the elements with the specific library you are using and you are good to go
I would recommend not using NaN, as it tries to parse strings. Instead, you can create an array and use the map function, in combination with the filter function.

display array values into select option tag in react js

I am trying to display array values into select tag, but all the array values displayed as single value. Please see below logic I added. Data is dynamic, I am getting data from backend like this ["Sankranti", "Sankranti 1"].
const [eventNameList, setEventNameList] = useState([])
var eventList = eventNameList.length > 0 ?
eventNameList.map((item,i) => {
console.log('list: ', item)
return (
<option>{item}</option>
)
})
:
'No Events'
<select>
{eventList}
</select>
please find below console screen shot
It looks that your list is nested inside another array so to fix this you could use flatMap instead of map
or you could just iterate throw the first element inside your nested array
const [eventNameList, setEventNameList] = useState([])
var eventList = eventNameList.length > 0 ?
eventNameList[0].map((item,i) => {
console.log('list: ', item)
return (
<option>{item}</option>
)
})
:
'No Events'
<select>
{eventList}
</select>

How to pass if condition loop output to a variable in reactjs

I need help to solve this
let someVar
render(
{
this.props.someData.map((items) =>
items.someotherData.map((item) =>
(item.data1 > 5 && item.data2 == "more") ? classNames({ "classname1": true })
: (item.data1 > 5 && item.data2 == "less") ? classNames({ "classname2": true })
: classNames({ "classname3": true })
))
}
<div className = { someVar } ></div>
)
I need my output of if loop to be pass to the variable
I tried many method. Nothing worked. Please give the solution
render() {
let someVar
this.props.someData.forEach(items =>
items.someotherData.forEach(item =>
item.data1 > 5 && item.data2 == 'more'
? someVar = 'classname1'
: item.data1 > 5 && item.data2 == 'less'
? someVar = 'classname2'
: someVar = 'classname3'
)
)
return <div className={someVar}></div>
}
I didn't really get what you were trying to do. Are you calling some function with the class names or something? Here is my best try to solve your problem though.
First we create the variable,
Then we do data processing. You shouldn't use map but instead the forEach if you are not returning anything. You are also overwriting the variable for each item (is this preferred behaviour?).
Then we actually return the React part of the code. Render function always needs to return JSX or null. Inside JSX we can use the someVar in the className. The final value of className needs to be a string. That's why we are putting strings to the someVar.

How to write the complicated rendering loop in React?

I am writing a nested loop in React. All I am seeing is the final return statements of tags. Where are the and going? Thank you.
{ this.state.data.headings.map( (heading, i) =>
<h3 key={i}>{heading}</h3> &&
// some headings do not have subheadings, tho
// they still have statements. deal with these cases first...
((this.state.data.subheadings[i].length === 0 &&
this.state.data.statements[i].map((statement, _j) =>
<p key={i+_j}>{statement}</p>)) ||
// cases where the group of statements has a subheading...
(this.state.data.subheadings[i].map((subheading, j) =>
<h4 key={i + j}>{subheading}</h4> &&
this.state.data.statements[i][j].map((statement, k) =>
<p key={i+j+k}>{statement}</p>))
)
)
)
}
A better way of doing this in my opinion is to separate this in different components each one of them taking care of one of the loops.in your case header,subheader,statement, etc.
There is everything ok with you code, except you can refactor it to make more readable.
Don't repeat yourself (DRY), always move duplicated code to separate component, in your example it is statement element. Also, i remove redundant key props.
render() {
const {headings, subheadings, statements} = this.state;
return headings.map((heading, i) =>
<div key={i}>
<h3>{heading}</h3>
{
subheadings[i].length
? subheadings[i].map((subheading, j) =>
<div key={j}>
<h4>{subheading}</h4>
<Statements statements={statements[i][j]}/>
</div>
)
: <Statements statements={statements[i]}/>
}
</div>
);
}
const Statements = ({statements}) => (
statements.map((statement, i) =>
<p key={i}>{statement}</p>
)
);
(omg folks,) feels like i had to take a picture to prove it...
solution, special thanks to a similar Q&A (I'm using React v15 out of an older template for Ether dApps)
{ headings.map( (heading, i) =>
[ <h3 key={i}>{heading}</h3>,
subheadings[i].length === 0 ?
statements[i][0].map( (statement, j) =>
<p key={j}>{statement}</p>,
) :
subheadings[i].map( (subheading, j) => (
[<h4 key={j}>{subheading}</h4>,
statements[i][j].map( (statement, k) =>
<p key={k} style={{color: 'green'}}>{statement}</p> )
]
))
])
}

Resources