Checking for Undefined In React - reactjs

I have a scenario where I'm passing data from a reducer into my react state.
data:
{
"id": 1,
"title": "Test",
"content": {
"body": "sdfsdf"
"image": "http://example.com"
}
}
Using componentWillRecieveProps, this works perfectly for retrieving the title.
componentWillReceiveProps(nextProps) {
this.setState({
title: nextProps.blog.title,
})
}
However, I'm having difficulty retrieving the nested fields. When I do this:
componentWillReceiveProps(nextProps) {
console.log("new title is", nextProps.blog.title);
console.log("new body content is", nextProps.blog.content["body"]);
this.setState({
title: nextProps.blog.title,
body: nextProps.blog.content["body"]
})
}
I get this error:
The error of an undefined body goes away after I click the debugger and the content is loaded. Is there anyway I can combat this issue?
I tried to check for undefined like this:
if (typeof nextProps.blog.content["body"] != 'undefined'){
But this doesn't work either and I believe it's because the blog is undefined.

What you can do is check whether you props is defined initially or not by checking if nextProps.blog.content is undefined or not since your body is nested inside it like
componentWillReceiveProps(nextProps) {
if(nextProps.blog.content !== undefined && nextProps.blog.title !== undefined) {
console.log("new title is", nextProps.blog.title);
console.log("new body content is", nextProps.blog.content["body"]);
this.setState({
title: nextProps.blog.title,
body: nextProps.blog.content["body"]
})
}
}
You need not use type to check for undefined, just the strict operator !== which compares the value by their type as well as value
In order to check for undefined, you can also use the typeof operator like
typeof nextProps.blog.content != "undefined"

I was face same problem ..... And I got solution by using typeof()
if (typeof(value) !== 'undefined' && value != null) {
console.log('Not Undefined and Not Null')
} else {
console.log('Undefined or Null')
}
You must have to use typeof() to identified undefined

In case you also need to check if nextProps.blog is not undefined ; you can do that in a single if statement, like this:
if (typeof nextProps.blog !== "undefined" && typeof nextProps.blog.content !== "undefined") {
//
}
And, when an undefined , empty or null value is not expected; you can make it more concise:
if (nextProps.blog && nextProps.blog.content) {
//
}

You can try adding a question mark as below. This worked for me.
componentWillReceiveProps(nextProps) {
this.setState({
title: nextProps?.blog?.title,
body: nextProps?.blog?.content
})
}

You can check undefined object using below code.
ReactObject === 'undefined'

Related

React Typescript: Object is possibly 'undefined'

I'm using react with typescript and was getting Object is possibly 'undefined' error when return language.toLowerCase().includes(selectedCategory) so I added a checking as in below. Error is gone but I'm not sure whether It can impact the performance. Please advice.
import { filter } from 'lodash';
...
return filter(channels, ({
language
}: Channels) => {
if (
language &&
language.toLowerCase() !== selectedCategory &&
selectedCategory !== 'all'
) {
return false;
}
return (
language && language.toLowerCase().includes(selectedCategory)
);
});
You can use Optional Chaining instead.
If the language is not null or undefined (nullish) it will access the property or method you want otherwise it will return undefined
If you're damn sure about language that it can't be null or undefined then use ! operator (non-null assertion operator) and rewrite your code like this:
import { filter } from 'lodash';
...
return filter(channels, ({
language
}: Channels) => {
return language!.toLowerCase().includes(selectedCategory);
});
Or You can use Optional Chaining instead.
No, that will not impact performance in any way, that's an incredibly inexpensive and common type of check to performance.
You can simplify it though with optional chaining
If you write language?.toLowercase(), it will evaluate to undefined if language is undefined, and a lowercase language if it is defined. So:
if (
language?.toLowerCase() !== selectedCategory &&
selectedCategory !== 'all'
) {
return false;
} else {
return language?.toLowerCase().includes(selectedCategory)
}
If you are sure that the object value is never null or undefined, You can use ! mark:
language!.toLowerCase().includes(selectedCategory)
If you are sure that language will never be undefined, you can use the ! non-null assertion operator to remove that warning.
language!.toLowerCase()
This is the best option in terms of runtime performance since when the code is transpiled into JavaScript the assertion operator is just removed.

Why doesnt my react if statement work with "or"

I am trying to get a console.log when my newPlan does not equal one of the selected options but it only works without the or statement "||"
Where am I going wrong?
if(newPlan !== "monthlyPlan" || "yearlyPlan"){
console.log("test2")
this.setState({
errorState: "error"
});
}
if(newPlan !== "monthlyPlan" && newPlan !== "yearlyPlan"){
console.log("test2")
this.setState({
errorState: "error"
});
}
EDIT - Explanation:
The && operator only becomes true if all conditions are true. In your case: if newPlan !== "monthlyPlan" is true and newPlan !== "yearlyPlan" is false the whole block becomes false.
Just give condition in both cases,
if(newPlan !== "monthlyPlan" ||newPlan !=="yearlyPlan"){
console.log("test2")
this.setState({
errorState: "error"
});
}

How can I setState in componentDidUpdate?

I'm trying to set the state based on API data. 'own' is a field in my API and it contains the Boolean value "true"... I'm storing the data I'm getting from the API in an object called passedXdayPassObj...
I want to set the value of checked property based on the API value of "own"..But it doesn't happen..
Following is my code...
componentDidUpdate(prevProps) {
let passedXdayPassObj;
const { xDayPass } = this.props;
if (xDayPass.xDay && xDayPass.xDayLoading === false && JSON.stringify(xDayPass.xDay) !== JSON.stringify(prevProps.xDayPass.xDay) && !this.props.pathname.includes("createChannel") && !this.state.isSubmit) {
passedXdayPassObj = {
own: xDayPass.xDay.own,
totalCount: xDayPass.xDay.totalCount,
totalValue: xDayPass.xDay.totalValue,
purchaseStart: moment(xDayPass.xDay.purchaseStart).format(),
purchaseEnd: moment(xDayPass.xDay.purchaseEnd).format(),
price: xDayPass.xDay.price,
restricted: false,
utilizeStart: xDayPass.xDay.utilizeStart,
utilizeEnd: xDayPass.xDay.utilizeEnd,
}
if (this.props.location && this.props.location.state && this.props.location.state.view || this.props.location.state.edit) {
this.props.initialize(passedXdayPassObj);
}
if (passedXdayPassObj && passedXdayPassObj.own) {
this.setState({
checked: passedXdayPassObj.own
});
}
}
}
You don't do state updates inside of compoonentDidUpdate() lifecycle methods it results in too many recursions ultimately crashing your app.
Shift the same code inside of componentDidMount() and everything will work fine.

Strange bug with Reducer

I maintain an object array in my Context that keeps track of validation errors in my input form. Here's an example of it populated with one object:
validationErrors = [{id: 0, message: 'Already exists', name: 'vin'}]
The message is displayed underneath the input element in question, prompting the user to enter a new value.
When the user does so, an async call is made to check if the new value already exists in the DB. Before that call is made, a call is dispatched to this reducer:
case CLEAR_VIN_INFO: {
return {
...state,
validationErrors: [...state.validationErrors.filter(
validationError => validationError.name !== 'vin' || validationError.id !== action.id)],
vehicles: state.vehicles.map((vehicle: Vehicle) => {
if (vehicle.id === action.id) {
return {
...vehicle,
makeModelYear: ''
};
} else {
return vehicle;
}
})
};
}
It's doing a few things but the main thing I want to focus on is that this specific validation error, with id: 0 and name: vin are removed from validationErrors. Watching what's happening in Chrome DevTools, I can indeed confirm that it is being removed. In other words, validationErrors is set to an empty array.
But upon returning from the async call, the following code produces unexpected results:
console.log(validationErrors.find(error => error && error.name === 'vin' && error.id === vehicle.id));
It reveals the following: {id: 0, message: 'Already exists', name: 'vin'}
How is this possible?
By the way, checking validationErrors in Chrome DevTools again shows that it's still empty!
My intuition is telling me that this bug is due to a previous version of validationErrors being referenced instead. I've never encountered this before though, so am not sure what to do.
Any ideas?
Update: As a sanity check of sorts, I made a call to this reducer instead:
case CLEAR_ERRORS: {
return {
...state,
validationErrors: []
};
}
This one absolutely clears validationErrors before the async call is made. Yet, upon returning from the async call, validationErrors is still populated! Now I'm completely baffled.
Try to fetch the state and access validationErrors inside your async call, then it should be good... but need more explanation in your question.

Strange results of typeof operator on DOM node element (angular 1)

I have a question regarding typeof DOM node.
Is that ok that Safari 5.1.7 on Windows return "function"?
typeof document.getElementsByTagName('head') === "function",
but on chrome
typeof document.getElementsByTagName('head') === "object"
This causes Angular 1 to break down on getting "jqLite" element:
jqLite(document.getElementsByTagName('head')) === Object[0]
as there are check in angular.js 1.6.1:
function JQLite(element) {
//...
if (argIsString) {
jqLiteAddNodes(this, jqLiteParseHTML(element));
} else if (isFunction(element)) {
//it returns true
jqLiteReady(element);
} else {
jqLiteAddNodes(this, element);
}
So basically my question is it suppose that isFunction called with dom element parameter return true? Is it Safari bug or not?

Resources