obj is undefined sometimes and works perfectly other times - javascript

In the computed propertys I am trying to match an ID received from an API to an array of objects with ID keys also received from an API and retrieve the name key from the matching ID object.
the obj variable occasionally throws an "obj is undefined" error but not consistently.
I think its to do with the IDs been async. Changed the function from arrow to classic function to not mess with the this scope.
data() {
return {
upComing: [],
popular: [],
topRated: [],
playingNow: [],
details: [],
genres: []
}
},
computed: {
genre: function() {
let list = this.upComing[0] ? this.upComing[0].genre_ids[0] : 0
let obj = this.genres.find(function(o) {
return o.id === list
})
return obj.name
}
},
created() {
let self = this
APIService.getUpcoming()
.then(response => {
self.upComing = response.data.results
//console.log(this.upComing)
})
.catch(error => {
console.log(`There was an error: ${error.response}`)
}),
APIService.getGenres()
.then(response => {
this.genres = response.data.genres
//console.log(this.genres)
})
.catch(error => {
console.log(`There was an error: ${error.response}`)
})
}
}
I get this TypeError: "obj is undefined" and this [Vue warn]: Error in render: "TypeError: obj is undefined"
and it throws them each twice. So i have 4 errors in the console but its just these 2 twice with a 1 second delay.

The error is that this.genres is [], so the computed property is computed when your component is mounted, so the result of this.genres.find(.... is undefined (because it can't find something in an empty list).
You can have a default value by using the || notation like this:
let obj = this.genres.find(function(o) {
return o.id === list
}) || { name: 'defaultName'}
This means that if nothing is found on the genres list, you still have a default result, then you can return obj.name with out having the error.
Also note that the genres variable is empty because the computed method is tun before your promise is resolved, and it runs again after you update that variable

You're most likely right about the issue being the async stuff, couldn't you just safeguard against undefined by doing something like this:
computed: {
genre: function() {
let list = this.upComing[0] ? this.upComing[0].genre_ids[0] : 0
let obj = this.genres.find(function(o) {
return o.id === list
})
return obj ? obj.name : '' // or whatever should be the default
}
},

Related

ERROR TypeError: Cannot read property 'push' of undefined, js engine: hermes

I need help filtering an array of objects in a typescript react native project using state to store array values and filter objects in the array
see error I keep getting in the method in question
cannot read property push of undefined
Appearing this way
LOG after item
LOG inside 300
ERROR TypeError: Cannot read property 'push' of undefined, js engine: hermes
see my code below
const handleSearchButtonPressed = () => {
console.log("inside handleSearchButtonPressed")
if (!itemListStore){
return
}
const text = searchText.toLowerCase()
console.log("inside 100")
// array of output objects
// eslint-disable-next-line array-callback-return
const filteredObjs = itemListStore.filter((item) => {
console.log(" 200")
console.log(" item is ")
console.log(item)
console.log(" after item")
const strTitle = JSON.stringify(item.title)
const strDesc = JSON.stringify(item.description)
const strLink = JSON.stringify(item.link)
const itemObj = {
title:strTitle,
description: strDesc,
link: strLink
}
if (strTitle.toLowerCase().match(text)) {
console.log("inside 300")
filteredObjs.push(itemObj)
console.log("inside 400")
}
})
console.log("filteredObjs", filteredObjs)
if (!text || text === "") {
setSearchText("",
)
} else if (!Array.isArray(filteredObjs) && !filteredObjs.length) {
// set no data flag to true so as to render flatlist conditionally
setNoData(true)
} else if (Array.isArray(filteredObjs)) {
setNoData(false)
setItemListStore(filteredObjs)
}
}
You're trying to both filter and map. This can more easily be achieved using either two separate operations or one single reduce.
Two operations...
const filteredObjs = itemListStore
.filter(({ title }) => title.toLowerCase().includes(text))
.map(({ title, description, link }) => ({
title: JSON.stringify(title),
description: JSON.stringify(description),
link: JSON.stringify(link),
}));
One reduce...
const filteredObjs = itemListStore.reduce(
(arr, { title, description, link }) => {
if (title.toLowerCase().includes(text)) {
return [
...arr,
{
title: JSON.stringify(title),
description: JSON.stringify(description),
link: JSON.stringify(link),
},
];
}
return arr;
},
[]
);

How to solve undefined error when trying to access a nested array in a React state variable?

I am trying to build a form in which you can dynamically add fields and subfields. As an example, my form looks like this:
Store information:
Name
Items inventory: [] (this is the nested array part,
you press a button and can add another item to the inventory)
***Buttons to add more items to this store***
***Buttons to add more stores***
The code I am using to achieve this looks like this. I have updated to reflect the answers that I got so far and also the proper syntax for (there was an issue with the closing tags)
function StoreForm() {
const [storeInputs, setStoreInputs] = useState([
{ storeName: "", items: [{ itemName: "" }] },
]);
///...
return (
{storeInputs.map((store,index) =>
{
//input data here
{store.items.map((item,i) =>
{
//This is where it throws the undefined error
//do something
}
)
}
}
)
)
}
The above code now works on the first run, but when I try to add another store to the form, it throws the undefined error again. Here is the code I am using for the buttons that add another store:
const handleRemoveStore = (index) => {
const list = [...storeInputs];
list.splice(index, 1);
setItemsInputs(list);
};
const handleAddStore = () => {
setItemsInputs([...storeInputs, { storeName: "", items: [{ itemName: "" }] }]);
};
Thank you for the answers thus far!
On
return (
{storeInputs.map(store,index) =>
{
//input data here
{storeInputs.items.map(item,i) =>
{
//This is where it throws the undefined error
//do something
}
}
}
)
You map two time on storeInputs, you need to do someting like :
return (
{storeInputs.map((input,index) =>
{
//input data here
{input.items.map((item,i) =>
{
//This is where it throws the undefined error
//do something
}
}
}
)
Be careful about the () around the params, you do :
x.map(a, index) => {})
In fact is :
x.map((a, index) => {})
The first ( is for the map methods, second is for the params of the function inside your map.
The storeInputs state hasn't any items property to map in the inner mapping. That property belongs to the store object mapped from the outer loop.
function StoreForm() {
const [storeInputs, setStoreInputs] = useState([
{ storeName: "", items: [{ itemName: "" }] },
]);
...
return storeInputs.map((storeInput, index) => {
// input data here
return (
...
{storeInput.items.map((item, i) => { ... })}
...
);
});
}

"TypeError": Cannot read properties of undefined in Vuejs?

It works like this: I have a table made in Vue, where I have some select options. This error appears when I have a grupo (group) and this group is not associated with a maquina (machine), what shouldn't happen, the objective is that only "-" appears. Throws an error in the console and does not show in my DataTable.
The error: [/Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'id_area')
This is the part of my code that I believe is causing this error:
computed: {
linhas () {
return this.lista.map(row => {
const group = this.grupos.find(g => g.id === row.id_grupo);
const machine = this.maquinas.find(m => m.id === group.id_maquina);
const area = this.areas.find(a => a.id === machine.id_area);
return ({
href: {path: this.editRoute + row.id},
cols: [
row.id,
row.tag,
row.descricao,
row.tipo === "ANALOGICA" ? "Analógica" : "Digital",
group.nome,
(machine || { nome: "-" }).nome,
(area || { nome: "-" }).nome
]
});
});
}
},
Can someone help me? I do not understand why this happening.
The array.find() method returns undefined if the value is not found (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find).
So if ther is no "machina" with the id group.id_maquina retrieve from the previous line, the line const machine = this.maquinas.find(m => m.id === group.id_maquina); set value undefined to the machine const.
And here's your error happens: reading id_area from machine that is undefined.
So you have to check if your variables are not undefined after array.find()
//...
const group = this.grupos.find(g => g.id === row.id_grupo);
if (group) {
const machine = this.maquinas.find(m => m.id === group.id_maquina);
if (machine) {
const area = this.areas.find(a => a.id === machine.id_area);
}
}
//...

Checking if !isLoading and state exists with useTracker meteor subscribe and findOne mongo

I normally can do this when I render the react component with an isLoading however if I try to use that to test that a variable is ready it complains that the map is undefined even though in the console it certainly is an array value that I am selecting. The isLoading returns undefined sometimes, and I've tried checking for if isLoading is !undefined and so here I am stuck.
const { leadsBuilder, isLoading } = useTracker(() => {
const noDataAvailable = { leadsBuilder: [] };
if (!Meteor.user()) {
return noDataAvailable;
}
const handler = Meteor.subscribe("leadsBuilder");
if (!handler.ready()) {
return { ...noDataAvailable, isLoading: true };
}
const leadsBuilder = LeadsBuilderCollection.findOne({ _id: params._id });
return { leadsBuilder };
});
if (!isLoading && leadsBuilder) {
let stateReplace = [];
leadsBuilder.inputs.map((leadInput, i) => {
stateReplace.push({ id: i, text: leadInput.name });
});
}
You're testing if leadsBuilder is truthy, but your invoking the .map on a property of leadsBuilder.
You should replace your condition by:
if(!isLoading && leadsBuilder?.inputs?.length) {
//your code
}
The ? test if the variable / property is defined, and then we use length because we want the array to not be empty

get value from a filtered array of objects

I have an array of objects each object contains a name property and a value property
what I want to do is return the value for the specified name
I am using a computed property
computed: {
statAlertCount() {
var stat = this.siteStatistics.filter(item => {
console.log(item);
return item.name == "site_alert_count";
});
console.log(stat[0]);
}
}
this code returns and object 'stat' which i can console out. it looks like this.
but if I try to access the value using stat[0].stat then I get the following error
app.js?id=f37d3d495892e39c6054:85474 [Vue warn]: Error in render: "TypeError: Cannot read property 'stat' of undefined"
I think you just need to return:
computed: {
statAlertCount() {
var stat = this.siteStatistics.filter(item => item.name === "site_alert_count");
return stat.length > 0 ? stat[0].stat : '';
}
}
An alternative solution using find:
computed: {
statAlertCount() {
const statItem = this.siteStatistics.find(item => item.name == "site_alert_count");
return statItem ? statItem.stat : "";
}
}

Categories