Cannot remove duplicates - reactjs

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)

Related

Object with similar attribute names loop, React

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>;
}
})}

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.

can not map array inside of object

I am lost here, can not find a way how to map through an array that is inside of object. I have received an object from API that includes an array wit values like this:
{
"shelters": [
{
"id": 1,
"name": "Útulok pre psov - TEZAS"
},
{
"id": 2,
"name": "OZ Tuláčik Brezno"
}
]
}
now I need to iterate through the array that is inside and take action on every item to populate the DOM.
my code is:
render() {
// const { isPending, shelters} = this.props;
if (this.props.isPending === false) {
var listOfShelters = this.props.shelters;
console.log('loaded', typeof(listOfShelters), listOfShelters)
return (
<div>
<select style={this.selector} name="útulky" onChange={this.sendId}>
{ listOfShelters.shelters.map(function(shelter, i) {
<option id={shelter.id}>{shelter.name}</option>
})}
</select>
</div>
)
} else if (this.props.isPending === true) {
console.log('fetching')
return (
<select style={this.selector} name="útulky" onChange={this.sendId}>
<option id='0'> Nahravam Data... </option>
</select>
)}
}
I get typeof always an object even if I do this.props.shelters.shelters which should be direct access to that array. if I do this.props.shelters.shelters.map nothing happens, my list of shelters does not get populated. it stays empty. Where do I make the mistake here?
I have found what the problem was. I had different set of parentheses in the .map function, I was using {} instead of (). Now it works like a dream.

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>

Remove specific value in array and add new updated value

I'm trying to remove existing specific value in an array before adding or push another updated value. My purpose is to avoid duplicate same id and value to array. What i'm trying to achieve is when onchange triggered check if that value is existing on array and if exist remove the old one and push the update value.
const [array, setnewarray] = useState([]);
function handlechangeselected(val,id){
var newarray = array;
const valueToRemove = id;
newarray.filter(item => item.id === valueToRemove);
newarray.push({ value: val, id:id });
setnewarray(newarray);
}
<select
onChange={(e) => handlechangeselected(e.target.value,row.ID)}
>
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
The first issue is that filter doesn't modify the array, but rather returns a new array. You're not using the returned array, so newArray is unchanged.
The other issue is that filter filters out out any values that return false from your callback, so you want your filter to return true for any items that don't match valueToRemove (in other words, !== instead of ===). You can also use .concat to chain after array.filter.
Here it is, simplified a bit:
const [array, setNewArray] = useState([]);
function handlechangeselected(value, id){
const newArray = array
.filter(item => item.id !== id)
.concat({ value, id });
setNewArray(newArray);
}

Resources