IF condition with OR inside doesn't work properly React JS - reactjs

I'm creating plugin for wordpress on react js and got an issue.
When user is entering in admin page and choose for example posts,
I'm checking if it is not a post, so user can't use customizable block:
if ( type !== "post" ) {
return <p>{__("Sorry, Post Navigation block is available only for Posts")}</p>;
}
and it's working, but in wordpress can be more types of posts, so I'm trying to use || inside this condition to check on another type:
if ( type !== "post" || type !== "portfolio" ) {
return <p>{__("Sorry, Post Navigation block is available only for Posts and Portfolio")}</p>;
}
And now is my problem, it's not working.
Variable type I'm getting from here:
const type = wp.data.select('core/editor').getCurrentPostType();
it returns a string.
What am I doing wrong?
Can you help me, please?

if ( type !== "post" || type !== "portfolio" ) {
This will always be true. If type is "post", then it will not be equal to "portfolio". If it's "portfolio", then it will not be equal to "post". And if it's anything else, it will not be equal to either.
Change it to use &&
if ( type !== "post" && type !== "portfolio" ) {

Related

Filter according to a value located in an array inside another array without setting the results in a new array

I'm using the pokeapi api and I want to filter the pokemon according to their types.
The problem is that I don't want to create a new array and I've tried multiple ways but none were working.
Here's the code :
pokedex.filter((pokedex) => {
if (type === 'all') {
return pokedex
} else {
return pokedex.types.filter(pt => pt.type.name === type)
}
})
Basically, I have a dropdown with the default value being "all" and the other options are each types. When you select an option it filters all the pokemon accordinh to the type selected.
Here's where the name of the type is stored in the api :
types [
0
type {
name //what i need to check
}
1
type {
name //what i need to check
}
]
I've also tried to use a forEach, a map and to use a includes but it didn't work.
I've logged the array returned after selecting a value but it returns true and false for each pokemon.
How can I use that to filter the pokemon returned ?

React - useParams() won't fail null / undefined check

I have two routes, /Profile which shows the user their own profile.
(it doesnt need to request this because their profile is already stored in state)
Then the second /Profile/.... which shows the user other profiles.
(it does need to request this because the state does not store all other users)
To have this functionality I have tried inputting this undefined / null check but it doesn't fail when the params are empty:
const getRequest = async () => {
const user_response = null;
console.log("param",params)
console.log("param id",params.id)
if (params !== null || params !== undefined) {
console.log("params true")
if (params.id !== null || params.id !== undefined) {
console.log("id true")
}
else{
console.log("false")
}
}
else{
console.log("false")
}
The following is the console outputs when no params are passed:
> param {}
> param id undefined
> params true
> id true
The following is the console outputs when params are passed:
> param {id: '321'}
> param id 321
> params true
> id true
How can I make it work as intended?
If your user ID can't be falsy (e.g. 0 is not a valid user ID, or '' isn't), then just
const userId = params?.id || null;
without any other fuss – userId it'll be either the ID if it's truthy, or null.
the empty object still return true, so if you want to check the object is empty or not you must do something like this:
const obj = {};
const isEmpty = Object.keys(obj).length === 0;
then you can check the param object with this
It looks like when you're not passing any params, "params" is default an empty object which is bypassing your if statementes ( because it is actually different than null and undefined)
You need a more clear condition; can use lodash library which has a method _.isEmpty() to check for empty objects or as other have stated use the Object.Keys length

"Object is possibly undefined" in React and TypeScript

certificate?: any;
<S.Contents>{certificate[0]}</S.Contents>
<S.Contents>{certificate[1]}</S.Contents>
<S.Contents>{certificate[3]}</S.Contents>
If the type of props is set to any and used as an index of an array, it works well. But if you change that any type to Array, Generic type'Array' requires 1 type argument(s). I get an error like this.
When I print typeof to the console, the object comes out, so when I change it from Array to object, I get an error other. "Object is possibly 'undefined'."
setCertificate(res.data.qualification.certificate);
Since it is an original array, I tried to create elements by turning it into map, but it also didn't work with a map is not a function error. I don't know what to do with me. Help.
You Always have to check for possible null or undefined values.
This is how I would do it to make it 100% safe
return (<div> {
certificate && certificate.length > 0 ? (
certificate.map((item, index) => (
<S.Contents key = {index}> {item}</S.Contents>
))
) : null
} </div>)
You get this error because you used an optional property for certificate. You need to add a check for undefined, to make sure it is actually defined.
Assuming your react function looks something like this, this would be a fast way to solve your issue:
function ReactComponent(props: {
certificate?: any[]
}) {
const certificate = props.certificate || [];
return (
{certificate.map((certificateItem) => (
<S.Contents>{certificateItem}</S.Contents>
))}
);
}
This line const certificate = props.certifate || []; assigns the first value if it is not undefined to the variable certificate otherwise the second. An if statement would also work but would be more verbose in this case:
function ReactComponent(props: {
certificate?: any[]
}) {
let certificate = props.certificate;
if(typeof certificate === "undefined") {
certificate = [];
}
return (
<div>
{certificate.map((certificateItem) => (
<S.Contents>{certificateItem}</S.Contents>
))}
</div>
);
}

Apollo boost - __typename in query prevent new mutation

I have a problem in my meteor/react/apollo (with boost) project. When I query data from the server, it adds __typename to every object and subobject in my query but it my case it creates a major issue as I normally reuse these data to send them to other mutation. Now the other mutation tell me there is an error because the __typename field is not defined in my graphql schema.
I tried to fix by adding the addTypename: false field to my apollo client but it didn't change anything (note I am using apollo boost, that may be why it is not sworking) :
const client = new ApolloClient({
uri: Meteor.absoluteUrl('graphql'),
addTypename: false,
request: operation =>
operation.setContext(() => ({
headers: {
authorization: Accounts._storedLoginToken()
}
}))
})
Also it seems than even if it worked it is not very optimized. It seems to me very problematic that a field is added to the query results and I am surprised not to find any clear solution online. Some proposed solution where :
filter manually on client side
add middleware to apollo
add the __typename field to all my schemas...
but none of them seem to fit the 'simplcity' apollo is suppose to bring for queries. I hope there is a simpler, more logical solution provided, but so far, could not find any.
Even if using apollo-client and not apollo-boost, you shouldn't set addTypename to false unless you have a compelling reason to do so. The __typename field is used by the InMemoryCache to normalize your query results, so omitting it will likely lead to unexpected behavior around caching.
Unfortunately, there is no "silver bullet" to this problem. Requesting a query and then using that query's data as the variable to some other query could be construed as misusing the API. The Type returned by a query and the Input Type used as an argument are completely different things, even if as Javascript objects they share one or more fields. Just like you can't use types and input types interchangeably within a schema, there shouldn't be an expectation that they can be used interchangeably client-side.
That also means that if you're finding yourself in this situation, you may want to take a second look at your schema design. After all, if the data exists on the server already, it should be sufficient to pass in an id for it and retrieve it server-side, and not have to pass in the entire object.
If you're using some query to populate one or more inputs and then using the value of those inputs inside a mutation, then you're presumably already turning the initial query data into component state and then using that in your mutation. In that scenario, __typename or any other non-editable fields probably shouldn't be included as part of component state in the first place.
At the end of day, doing these sort of manipulations will hopefully be the exception, and not the rule. I would create some kind of helper function to "sanitize" your input and move on.
function stripTypenames (value) {
if (Array.isArray(value)) {
return value.map(stripTypenames)
} else if (value !== null && typeof(value) === "object") {
const newObject = {}
for (const property in value) {
if (property !== '__typename') {
newObject[property] = stripTypenames(value[property])
}
}
return newObject
} else {
return value
}
}
From
here. '__typename' can be removed with the following helper function
const cleanedObject = omitDeep(myObject, "__typename")
const omitDeep = (obj, key) => {
const keys = Object.keys(obj);
const newObj = {};
keys.forEach((i) => {
if (i !== key) {
const val = obj[i];
if (val instanceof Date) newObj[i] = val;
else if (Array.isArray(val)) newObj[i] = omitDeepArrayWalk(val, key);
else if (typeof val === 'object' && val !== null) newObj[i] = omitDeep(val, key);
else newObj[i] = val;
}
});
return newObj;
};
const omitDeepArrayWalk = (arr, key) => {
return arr.map((val) => {
if (Array.isArray(val)) return omitDeepArrayWalk(val, key)
else if (typeof val === 'object') return omitDeep(val, key)
return val
})
}
You shouldn't remove the __typename. They are for the cache and also needed for union types. Probably should wait for an update from apollo.
Unfortunately I am also have issue now and I couldn't find a proper solution. First I used to simply delete all the type names, but now I have issue with the union types.

How to check if variable trusted as HTML is empty in AngularJS

I have this situation:
<div ng-bind-html="model"></div>
<div ng-if="!model">Echo me if model is empty</div>
And in controller:
model = $sce.trustAsHtml(model);
How can I render second <div> only if model is (was before trusting it) empty string? I tried ng-if="!model" and ng-if="model == ''" but neither of these does work.
As #MMhunter said, it should work (if model is empty string). I didn't include some details because I thought these are not relevant.
Basically, model is fetched via RESTful service, and empty model were saved in database as null. Because of that, neither !model nor model == '' worked. Now, ng-if is:
<div ng-if="model == '' || model == null">Echo me if model is empty</div>
and it works.
Conclusion: $sce.trustAsHtml(str) preserves null value (as well as undefined and empty string). AngularJS source:
function trustAs(type, trustedValue) {
var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
if (!Constructor) {
throw $sceMinErr('icontext',
'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
type, trustedValue);
}
if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') {
return trustedValue; // <<< THIS IS RESPONSIBLE >>>
}
// All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting
// mutable objects, we ensure here that the value passed in is actually a string.
if (typeof trustedValue !== 'string') {
throw $sceMinErr('itype',
'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
type);
}
return new Constructor(trustedValue);
}

Resources