Making my function general as possible for checking a state - reactjs

I want to create a function that can be general as possible but It doesn't work now.
I have two case :
Check if the state of a state is not empty or true and if my item is equal to him, I want to reset him by calling resetState() and set to false and empty string
Check if the state of a state is not empty and if my item is equal to him, I want to reset him by calling resetState()and the empty string
My problem is : I try to replace stateItem.checkedA by something like stateItem.item to avoid repetitions but doesn't work for me, is it possible in react to do that ?
This is what I have :
const [stateBoolean, setStateBoolean] = React.useState({
checkedA: false,
checkedB: false
});
const [stateItem, setStateItem] = React.useState({
checkedA: "",
checkedB: "toto",
checkedC: "onlyHere not in Boolean"
});
const check = (listState) => {
listState.map(item => {
(stateBoolean.checkedA === true || stateItem.checkedA !== "") &&
item === "checkedA"
? (resetChange("checkedA", "stateItem"),
resetChange("checkedA", "stateBoolean"))
: null;
(stateBoolean.checkedB === true || stateItem.checkedB !== "") &&
item === "checkedB"
? (resetChange("checkedB", "stateItem"), resetChange("checkedB", "stateBoolean"))
: null;
stateItem.checkedC !== "" && item === "checkedC"
? resetChange("checkedC", "stateItem")
: null;
});
};
What I expected, but not working:
const checkWanted = (listState) => {
listState.map(item => {
(stateBoolean.item === true || stateItem.item !== "") &&
(item === "checkedB" || item === "checkedA")
? (resetChange(item, "stateItem"), resetChange(item, "stateBoolean"))
: null;
stateItem.checkedEOther !== "" && item === "checkedEOther"
? resetChange(item, "stateItem")
: null;
});
};
Any idea?

Use stateBoolean[item] instead, you can access properties of an object like an array
The function map return a new Array mdn description
If you want to iterate on a array and do something you should use forEach or a for loop.

Related

Ternary into ternary using react jsx [duplicate]

I'm missing something if someone can please explain it to me. I'm trying to re-write existing code into the ternary operator way.
I'm getting the following console error :
Uncaught SyntaxError: Unexpected token }
which I understand there's a condition not properly formatted which I can't seem to find. So I'm not sure what I'm missing or if I maybe misunderstand something in the filter function? Isn't the ? item.verified === true not suppose to automatically return the objects that's true?
var engagement = "social";
var audience = [{ 'verified': true, 'name': 'Steve'},
{ 'verified': false, 'name': 'Phil'},
{ 'verified': true, 'name': 'Jason'}];
let data = [];
data = audience.filter((item) => {
(engagement === "social")
? item.verified === true
: (engagement === 'social-crm')
? item.verified === false
: (engagement === 'all')
? item
})
The syntax that I understand:
data = audience.filter((item) => {
if (this.engagement === 'social-crm') {
return item.verified === true;
} else if (this.engagement === 'social') {
return item.verified === false;
} else if (this.engagement === 'all') {
return item;
}
});
Here's the fiddle I've been trying to play around with:
https://jsfiddle.net/phfilly/ya73e325/7/
Yup. Your syntax isn't right. To understand why your code isn't working, it would help if you were to re-write your if-else statements a bit.
if (this.engagement === 'social-crm') {
return item.verified === true;
} else if (this.engagement === 'social') {
return item.verified === false;
} else if (this.engagement === 'all') {
return item;
}
To this:
if(this.engagement === 'social-crm') { return item.verified === true; }
else {
if(this.engagement === 'social') {item.verified === false; }
else {
if(this.engagement === 'all') {return item;}
}
}
Now, ternary operators follow a similar nested fashion.
cond1 ? val1 : ( val2 )
Where val2 => cond2 ? val3 : (val4)
Where val4 => cond3 ? val5 : val6
So, now you can rewrite your expression like this:
this.engagement === 'social-crm' ? item.verified === true :
(this.engagement === 'social' ? item.verified === false :
(this.engagement === 'all' ? item : null))
The parenthesis matters here, because it closely mimics the nested if-elses from above.
Also note that for the inner most expression, a return value in the else must be specified. I've set it to null but you can return what you want. Do note this is the actual reason your code was failing. Apologies if the answer was long but I wanted to help you understand nested ternary operators.
A ternary operator looks like this:
something = (condition) ? a_value : a_different_value;
You forgot : a_different_value on the last case.
A nested ternary operator looks like this:
something = condition ? nested_condition ? value_if_both_conditions_are_true
: value_if_nested_condition_is_false : value_if_condition_is_false;
This works even without parentheses, but as others have mentioned, it can be hard to read. Especially when multiple conditions are checked, by use of && or || in the condition parts of this example.
Try this
You have to have a Condition for the Ternary operator as pointed by #Quentin
data = audience.filter((item) => { (engagement === "social") ?
item.verified === true : (engagement === 'social-crm') ?
item.verified === false : (engagement === 'all')?
item : null})
Deep nesting can write in a simpler way like this for ternary if-else
let userName = 'Amoos'
let isStudent = false
let age = 7
userName
? console.log(`User name: ${userName} 😊`)
: console.log('Unknow user');
isStudent ? console.log("Yes, is student 👨‍🎓")
: console.log('No, not a student 👨‍🎓');
(age<18) ? console.log("Younger 👶")
: console.log("Elder 😁")

output-task.js:171 Uncaught TypeError: Cannot assign to read only property 'multiDrag' of object '#<Object>'

I am getting this error when I am trying to update my state using props basically when my condition matches the flag would certainly go back to its initial state value but it is showing error in this case.
var finalVal;
if (
typeof bigFinalValue === "undefined" ||
bigFinalValue.length < 1 ||
this.props.singleDrag === true
) {
console.log("here he is", this.props.singleDrag);
finalVal = <Content>{task.word}</Content>;
this.props.multiDrag = false;
}
if (
(typeof bigFinalValue === "undefined" || bigFinalValue.length > 1) &&
this.props.multiDrag === true
) {
console.log("bigFinalValue", bigFinalValue);
console.log("selectionCount", selectionCount);
console.log("and here he is again...");
finalVal = <Content>{bigFinalValue}</Content>;
this.props.multiDrag = false;
}
Here the error is pretty obvious. You are trying to set props to false.
this.props.multiDrag = false; //wrong
Props are READ ONLY. You can read the article below to get a better understanding how it works.
https://itnext.io/what-is-props-and-how-to-use-it-in-react-da307f500da0#:~:text=%E2%80%9CProps%E2%80%9D%20is%20a%20special%20keyword,from%20one%20component%20to%20another.&text=Furthermore%2C%20props%20data%20is%20read,be%20changed%20by%20child%20components.

Filter data based on 2 values

I am creating an application with a requirement for 2 search bars. One to search by name and another to search by tag. The search should also work when the user puts both name and tag in the searchbars.
The data from the api is in the format
{
"students" : [
{
"city": "city",
"company" : "company",
"email" : "email",
"firstName" : "firstName",
"grades" : ["12", "54"],
"id" : "1",
"lastName" : "lastName",
"pic" : "url",
"skill" : "skill"
},
],
}
My application is running on https://temp-application.netlify.app/
Currently the application does search with name as it is supposed to be.
But as soon as I attach search by tag functionality with it. Everything breaks down.
This is how I implemented searching by both name and tag.
useEffect(() => {
let filteredResults = results.filter((result) => {
const name = result.firstName + " " + result.lastName;
const isName = name
.toLowerCase()
.includes(searchName.toLowerCase());
const tags =
result.tag !== undefined ? result.tag.toString() : false;
const isTag =
typeof tags === "string"
? tags.toLowerCase().includes(searchTag.toLowerCase())
: false;
return isName && isTag;
});
setStudents(filteredResults);
}, [searchName, searchTag]);
Notice that 'tag' array is not present in the object returned by the API
The link you gave is not working.
For Tags, you are searching in the "tag" string in the Student(result) object but there is no key named tag in the given data.
Even if you have the tag key, you are probably not getting the result because you are doing a "&&" instead of "||"
I solved it. The problem was that I was trying to do the search in one-go. But instead I needed to make a if-else chain to achieve the result.
Here is the final function
let filteredResults = results.filter((result) => {
const name = result.firstName + " " + result.lastName;
const tags =
result.tag !== undefined ? result.tag.toString() : false;
if (searchName !== "" && searchTag === "") {
return name.toLowerCase().includes(searchName.toLowerCase());
} else if (searchName === "" && searchTag !== "") {
return typeof tags === "string"
? tags.toLowerCase().includes(searchTag.toLowerCase())
: false;
} else if (searchName !== "" && searchTag !== "") {
const isName = name
.toLowerCase()
.includes(searchName.toLowerCase());
const isTag =
typeof tags === "string"
? tags.toLowerCase().includes(searchTag.toLowerCase())
: false;
return isName && isTag;
} else if (searchName === "" && searchTag === "") {
return true;
}
return false;
});
setStudents(filteredResults);
}, [searchName, searchTag]);

react filtering an object of arrays

I'm trying to find a better way to remove value pairs of an object that contain an empty string ""
my current state is:
this.state = {
searchParams:{
query: '',
colors: [],
text: '',
legalities: '',
setName: '',
pageSize: 4
}
}
I know this won't work with my state since it isn't an array, but something like this is what i'm trying to achieve right now
var search = this.state.searchParams.filter(function (el) {
return el !== "";
});
could anyone point me in the right direction and explain a better way to do this with an object, thanks :) ?
filter only use for a array, not is a object.
You can try my code
let searchParams =
Object.keys(this.state.searchParams)
.filter( key => this.state.searchParams[key] !== '' );
this.setState({searchParams })
You can use Object.entries and Object.fromEntries.
const filteredObject = Object.fromEntries(
Object.entries(searchParams)
.filter(([key, value]) => value !== "")
);
Will create anew object with all the keys for which the value was "" removed.
You can filter it this way with reduce method. Since it is an object, you have to combine object prototype .keys with array prototype .reduce to filter it.
const searchParams = {
query: '',
colors: [],
text: '',
legalities: '',
setName: '',
pageSize: 4
}
const notEmpty = Object.keys(searchParams).reduce((nonEmptyObj, currentKey) => {
if (searchParams[currentKey] !== '') {
nonEmptyObj[currentKey] = searchParams[currentKey];
}
return nonEmptyObj;
}, {})
console.log(notEmpty);
use Object.keys. In your case like this:
var search = Object.keys(this.state.searchParams).filter(el => {
// do something
})
the most simple way is by using Object.keys method and then iterate the whole object. then check if searchParams[ele] is true and add in another object.
var newObj = {};
Object.keys(this.state.searchParams).forEach(ele => {
if (searchParams[ele]) {
newObj = { ...newObj, [ele]: searchParams[ele] };
}
});
console.log(newObj); // new object generated with empty values eliminated
this.setState({searchParams:newObj})
If you want to filter out empty strings and strings (with white spaces only) as well, then
we have trim the string and then check its length. If its string and its length is 0 after trimming, then its considered as empty and will be filtered out.
const params = this.state.searchParams
Object.keys(this.state.searchParams).filter(key =>
!(typeof params[key] === 'string' && params[key].trim().length === 0)
)
If you don't want to trim, then:
const params = this.state.searchParams
Object.keys(this.state.searchParams).filter(key => params[key] !== '')
I would highly suggest you to not to use semicolon, as it takes space and JS can now ignore semicolon as well. Also, not to use double quotes unless required.

How to use the ternary operator in react?

i want to use ternary operator instead of if else conditions in react.
What i am trying to do?
I have an array of object type named 'list_info' which has type, recipient_idand recipient_email attributes.
Now i have a method named "get_text" which returns text whose value is string "to you" or the recipient email.
If the list_info type is "type_1" and props.current_user_id === list_info.recipient_id then it should
return nothing.
If the list_info type is "type_1" and props.current_user_id !== list_info.recipient_id then it should
return the list_info.recipient_email.
Now when the list_info type is anything other than "type_1" and and props.current_user_id ===
list_info.recipient_id then it should
return string "to you".
If the list_info type is anything other than "type_1" and props.current_user_id !==
list_info.recipient_id then it should return the list_info.recipient_email.
So to accomplish the above conditions i have the "get_text" method as below,
get_text = () => {
const list_info = this.props.list_info;
let text;
if (this.props.list_info.type === 'type_1') {
if (this.props.current_user_id === list_info.recipient_id) {
text = '';
} else {
text = list_info.recipient_email;
}
} else {
text = this.props.current_user_id === list_info.recipient_id
? 'you'
: list_info.recipient_email;
}
return <strong key={list_info.type}>{text}</strong>;
};
The above code works. But i think it could be made even more simple to read using ternary operator. could someone help me fix this. thanks.
Generally writing nested ternary operators will make the code unreadable. You can refactor your code as below, if you have more and more conditions/logic coming in, you can probably start using switch statement.
get_text = () => {
const { list_info, current_user_id } = this.props;
const meTextByType = list_info.type === 'type_1' ? "" : "you";
let text = current_user_id === list_info.recipient_id ?
meTextByType :
list_info.recipient_email;
return <strong key={list_info.type}>{text}</strong>;
};
get_text = () => {
const { list_info, current_user_id } = this.props;
const { type, recipient_id, recipient_email } = list_info;
const meTextByType = type === 'type_1' ? "" : "you";
let text = current_user_id === recipient_id ? meTextByType :brecipient_email;
return <strong key={type}>{text}</strong>;
};
How about local functions that describe exactly what each condition is, and by the looks of you only ever return 2 values, either 'to you' or the recipient_email prop.
getText = () => {
const isToYou = () => listInfoType !== 'type_1' && recipientId === userId
return isToYou() ? 'To You' : recipientEmail
}

Resources