Compare dates in jsx - reactjs

I am trying to display events for the same day by comparing dates.
How can I use a conditional statement in my map?
{events && events.length && events.map((event) => <Text>{event.author}
{
(currentDay == date)
? 'same'
: 'different'
}
</Text>)
}
How would be the best way to do this?

You can always use isSame from momentjs
moment(currentDay).isSame(date, 'day')
If you need to do a lot of checks to do in your map, remember you can write it like this as well
events.map((event) => {
const text = // your conditional stuff
// some more code if necessary
return (
<Text>{text}</Text>
)
}

Related

How to access values by key from modified React final form

I was making confirmation when the user tried to close the form by modified and values length > 0.
if (modified) {
return (
Object.keys(modified).filter(
(modifiedItem) => modified[modifiedItem] && values[modifiedItem]?.length > 0,
).length > 0
)
}
Everything is working fine until there are values with an array:
when I try to access by values[answers.0.icon] there is undefined, of course, it should be accessed by values.answers[0].icon, by is it possible to do it when iterating modified keys? Or another way should be appreciated.
Thank you beforehand.
Below screenshots of values:
Modified keys:
I'd suggest to include lodash and use the get function. This will resolve the "path" for you.
For example _.get(values, modifiedItem).
More info can be found at https://lodash.com/docs/4.17.15#get
you could add undefined and null in the if statement, to check if it's true and not undefined and not null before it filter else it will be null or you can put something else.
if (modified && modified !== undefined && modified !== null) {
return (
Object.keys(modified).filter(
(modifiedItem) => modified[modifiedItem] && values[modifiedItem]?.length > 0,
).length > 0
)
}
else {
null
}
You can perhaps check for such situation if its an array and treat it differently.
I agree with solution provided by #Stijn answer, however if you dont wanna carry unnecessary baggage of Lodash you can use below code.
const parseDeep = (obj, path, def) => (() => typeof path === 'string' ?
path.replace(/\[(\d+)]/g,'.$1') : path.join('.'))()
.split('.')
.filter(Boolean)
.every(step => ((obj = obj[step]) !== undefined)) ? obj : def
if (modified) {
return (
Object.keys(modified).filter(
(modifiedItem) =>
Array.isArray(modifiedItem) ?
modified[modifiedItem] && parseDeep(values, modifiedItem, false) : //modify as required
modified[modifiedItem] && values[modifiedItem]?.length > 0,
).length > 0
)
}

How can call multiple function in React ternary if else condition

I can not call multiple functions in react js if else ternary condition.
const preATCHandler = ( id, itemNumber ) => {
itemNumber > 0
? (setAtcBtn(false), setQty(itemNumber), dispatch(addToCart(id, Number(itemNumber))))
: (dispatch(removeFromCart(id)), setAtcBtn(true))
}
I can not call multiple functions in ternary operator because it is inline condition.
Finaly take help from wxker.
I use this.
const preATCHandler = ( id, itemNumber ) => {
if (itemNumber){
setAtcBtn(false);
dispatch(addToCart(id, Number(itemNumber)));
}else {
dispatch(removeFromCart(id));
setAtcBtn(true);
}
}

Speeding up a very slow Vuetify Filter method

I have a working filter method, however it is very slow. text input is passed into $store, and a function is applied to see if anything in an array is a partial match for the text-input. Essentially I am using a computed function to iterate over to display components.
This is effectively the first thing I've tried. It does work in some capacity, but is unbelievably slow and unoptimized.
<v-flex
v-for="myFolder in folderFilter"
:key="myFolder"
xl2
md4
xs6
justfy-space-around
style="padding-top:50px;"
>
<FolderIcon
:folderName="myFolder.folderName"
:folderDescription="myFolder.folderDescription"
:isReadOnly="myFolder.isReadOnly"
:addImage="myFolder.addImage"
:updateHeader="myFolder.updateHeader"
></FolderIcon>
</v-flex>
computed: {
folderFilter(): Folder[] {
let returnFolder: Folder[] = new Array();
if (
this.$store.state.search === "" ||
this.$store.state.search === null
) {
return this.$store.state.displayArray;
} else {
this.$store.state.displayArray.forEach((element: Folder) => {
if (
element.folderName
.toLowerCase()
.includes(this.$store.state.search.toLowerCase())
) {
returnFolder.push(element);
}
});
}
return returnFolder;
}
},
It does work, however when I add more input it is very laggy to take input.

Filter with two arguments\parameters

I have a method that should return a list.
I would like to filter the data by two parameters and not one.
So far I have done the following but that's an unwanted result so I've probably done something wrong
performFilterByRunnerName(
filterByCompetition: string, filterByRunnerName: string
): IRunners[] {
return this.runners
.filter(x => x.runnerName === filterByRunnerName)
.filter(x => x.competitionId === filterByCompetition);
}
use && operator
performFilterByRunnerName(
filterByCompetition: string, filterByRunnerName: string
): IRunners[] {
return this.runners
.filter(x => x.runnerName === filterByRunnerName && x.competitionId === filterByCompetition);
}
Doing two filters in sequence means that
You get a first set of values
In this set, you create a new set of values
If it isn't what you want, you should probably explain what it is that you are expecting.
But to inform you, you have :
OR
.filter(x => x.runnerName === filterByRunnerName || x.competitionId === filterByCompetition);
AND
.filter(x => x.runnerName === filterByRunnerName && x.competitionId === filterByCompetition);
XOR
.filter(x =>
(x.runnerName === filterByRunnerName && !(x.competitionId === filterByCompetition)) ||
(!(x.runnerName === filterByRunnerName) && x.competitionId === filterByCompetition));
It's hard to know exactly what's going on from your post. But I'll give it a go:
You have a function,
That accepts two values,
and returns an array,
that is first filtered by one value,
which is passed along the pipe,
and is then filtered by the other value.
That's not the same as, "I am filtering an array by two values," which implies the two filters are a simple "&&". They're not. I've seen this subtle (though important) difference cause an issue many times.
A very simple way to go about it: you can just do as many comparisons inside of one filter as you want.
performFilterByRunnerName(
filterByCompetition: string, filterByRunnerName: string
): IRunners[] {
return this.runners
.filter(x => ( x.runnerName === filterByRunnerName && x.competitionId === filterByCompetition ) );
}
If your end game is to "get all objects that match these two criteria" this should run predictably.

How to add case insensitive sorting in react table?

By default, react table sorting is case sensitive.
In order to make it insensitive we have to write a custom sort function.
I like this answer from https://github.com/react-tools/react-table/issues/335.
This would help.
For case insensitive and numbers sorting pass sortTypes in table props like this:
useTable({
sortTypes: {
alphanumeric: (row1, row2, columnName) => {
const rowOneColumn = row1.values[columnName];
const rowTwoColumn = row2.values[columnName];
if (isNaN(rowOneColumn)) {
return rowOneColumn.toUpperCase() >
rowTwoColumn.toUpperCase()
? 1
: -1;
}
return Number(rowOneColumn) > Number(rowTwoColumn) ? 1 : -1;
}
}
})
//function to sort the results
function filterCaseInsensitive(filter, row) {
const id = filter.pivotId || filter.id;
return (
row[id] !== undefined ?
String(row[id].toLowerCase()).startsWith(filter.value.toLowerCase())
:
true
);
}
// react table code goes here
<ReactTable
data={data}
columns={columns}
filterable
defaultFilterMethod={(filter, row) => filterCaseInsensitive(filter, row) }
/>
The question mentions sorting but links to filtering. For custom sorting the app's owner mentions on Github to pass a sortTypes: { alphanumeric: MyCustomFunc } in the table props, like this:
useTable({
columns,
sortTypes: {
alphanumeric: (row1, row2, columnName) => {
return compareIgnoreCase(
row1.values[columnName],
row2.values[columnName]
)
},
},
},
useSortBy
)
The proper way to sort a column with react-table and with a case-insensitive approach, would be to use sortType on a column and then provide a custom function.
/**
*
* React Table helper to sort tables
* with case-insensitive support
*
*/
export const customInsensitiveCompare = (
rowA: Row,
rowB: Row,
columnId: string,
desc: boolean
) => {
const valueA = rowA.values[columnId].toLowerCase();
const valueB = rowB.values[columnId].toLowerCase();
if (desc) {
return valueA.localeCompare(valueB) > 0 ? 1 : -1;
}
return valueB.localeCompare(valueA) > 0 ? -1 : 1;
};
If you do not use Typescript just remove the types and everything will work fine. Take care that we need to return only -1 or 1 and localeCompare sometimes can return 0 or even different values according to MDN docs, that why we assign only -1, 1 as react-table expects.
(firstRow, secondRow, accessor) => {
// get from lodash
const firstValue = get(firstRow.values, accessor, '');
const secondValue = get(secondRow.values, accessor, '');
return firstValue > secondValue ? 1 : -1;
}
Above is the solution I used to assign to "alphanumeric", which covered both cases. Because, as in many programming languages, strings are compared lexicographically hence we need not change the case. And even comparing with numbers works fine.

Resources