I am trying to map multiple Database entries to an Object, so I can filter it.
async autocomplete(interaction) {
const focusedValue = interaction.options.getFocused();
let choices = await items.findAll({
attributes: ['itemID', 'desc_de'] });
const jsondata = JSON.stringify(choices);
const json = JSON.parse(jsondata);
const itemObj = json.map(function(item) {
return {
itemID: item.itemID,
item_desc: item.desc_de,
};
});
const filtered = itemObj.filter(choice => choice.item_desc.toLowerCase().includes(focusedValue.toLowerCase()));
await interaction.respond(
filtered.map(choice => ({name: choice.item_desc, value: choice.itemID})),
);
The issue I am having is, apparently choice.item_desc is NULL somehow, I am unsure, what I am doing wrong here.
The error is
TypeError: Cannot read properties of null (reading 'toLowerCase')
Before I had an object, which was only holding the itemID and with that it was working fine.
focusedValue may be null to which you cannot apply .toLowerCase(). Try setting a default value to that given that function exists outside the scope of the code provided
Related
I had read this post How to return values in javascript. But my question is how do we get the Map value if we derived it from asynchronous function like in this code below:
async function exampleToken(profile) {
let response;
const tkAdmin = {
admin: true,
};
const tkInvestors = {
investor: true,
};
if (profile == 1) {
response = {
"token": tkAdmin,
"code": 1,
};
} else if (profile == 2) {
response = {
"token": tkInvestors,
"code": 2,
};
}
return Promise.resolve(response);
}
I want to use the value from this function using this code:
const response = await exampleToken(profile);
// Is this correct:
const code = response.code;
const token = response.token;
// or
const code = response["code"];
const token = response["token"];
Please, help me out. Any tips and trick will be great. Thank you very much for spending time to read this post.
Both are correct in Javascript,
1- Dot property accessor: object. property.
2- Square brackets property access: object['property']
3- Object destructuring: const { property } = object.
This style is named Object Dot Notation access
const code = response.code;
const token = response.token;
and this one is Object Bracket notation access
const code = response["code"];
const token = response["token"];
Read more here
learning React but I'm trying to map an array of objects in a dropdown box.
I'm getting a "Uncaught TypeError: ids.map is not a function".
Why am I getting this error when I have set the loadedIds I get from the GET request into useState's setIds?
https://jsfiddle.net/4jh9c6dv/53/
Thank you for helping a beginner :')
function Dropdown ()
{
const [ids, setIds] = React.useState([]);
React.useEffect(() => {
request.get(endpointIds).then((response) => {
setIds(response.data);
const loadedIds = [];
for (const id in response)
{
loadedIds.push({
id: ids,
});
}
setIds(loadedIds);
});
}, []);
const idsList = ids.map((id) =>
(
<option>id</option>
));
You do not need to use setIds(response.data);. Remove that.
response.data is not an array, response.data.ids is. That is why you get the error.
EDIT : Use for of instead of for in.
for of is used to iterate over items of an array/iterable object.
for in is used to iterate over index.
response.data should be response.data.id
you also forgot curly braces {id}
I'm creating a flashcard app and I'm currently trying to set the front side of the flashcard to some text from an API.
My state:
const [deckWithCards, setDeckWithCards] = useState([]);
deckWithCards is a deck of flashcards and it looks like:
{name: 'Test Name', description: 'Test Description', id: 3, cards: Array(4)};
When I do deckWithCards.cards I get:
[{id: 1, front: 'Front of card', back: 'Back of Card', deckId: 1}]
If I was to have 4 cards in a deck, I'll get an array with 4 of these objects with the corresponding data.
I need access to all of this information however, when I try to do deckWithCards.cards.front, I get "Cannot read property 'front' of undefined."
I also tried looping through the cards array like:
let arr = [];
let allCards = deckWithCards.cards;
for (let i = 0; i < allCards.length; i++) {
arr.push(allCards.front);
}
This gave me: "Cannot read property 'length' of undefined."
How do I gain access to the items in this cards array?
Helper functions:
export async function readDeck(deckId, signal) {
const url = `${API_BASE_URL}/decks/${deckId}?_embed=cards`;
return await fetchJson(url, { signal });
}
export async function listCards(deckId, signal) {
const url = `${API_BASE_URL}/cards?deckId=${deckId}`;
return await fetchJson(url, { signal });
}
How I set my State:
useEffect(() => {
const abortController = new AbortController();
readDeck(deckId, abortController.signal)
.then(setDeckWithCards)
.catch(setError)
listCards(deckId, abortController.signal)
.then(setCards)
.catch(error)
return () => abortController.abort();
}, []);
There is a moment in time while your useEffect and your fetch are still running before you set the cards. During that time, the value of deckWithCards is going to be the initial value that you provided in your useState. Your component has to be built in a way where it can run properly and render properly with that initial value. If the eventual value of the resolved deck is an object, then it makes no sense that your initial value is an empty array.
const [deckWithCards, setDeckWithCards] = useState([]);
I recommend that you set the initial state to null or undefined. Before you access any properties on deckWithCards, you have to check that it has been set to an actual value.
const [deckWithCards, setDeckWithCards] = useState(null);
const allCards = deckWithCards ? deckWithCards.cards : [];
Here we check if deckWithCards is truthy (not null). If we have a deck, then we access the cards from the deck. If it's still null, we use an empty array. Either way, allCards will always be an array that you can map, loop through, etc.
const fronts = allCards.map( card => card.front );
return (
<ul>
{allCards.map( (card) => (
<div className="card" key={card.id}>
{card.front}
</div>
))}
</ul>
)
First of all, the first state is []
const [deckWithCards, setDeckWithCards] = useState([]);
So in the very first run I except that deckWithCards is an array with no property cards. This can trigger the error you're encountering.
Otherwise, if deckWithCards is an array of objects, then to access the cards of, let's say, first object, you need to enter deckWithCards[0].cards
If instead you are correctly setting the value of deckWithCards with an object as you described above, deckWithCards.cards should correctly return the excepted list of cards.
I am trying to add the id's to array if those are available like as below
export const extractOpaqueConstructionType = library => {
const opaqueConstructionSecondaryIds= [];
opaqueConstructionSecondaryIds.push(library?.exteriorWallId);
opaqueConstructionSecondaryIds.push(library?.exteriorFloorId);
opaqueConstructionSecondaryIds.push(library?.roofId);
opaqueConstructionSecondaryIds.push(library?.interiorWallId);
opaqueConstructionSecondaryIds.push(library?.interiorFloorId);
opaqueConstructionSecondaryIds.push(library?.belowGradeWallId);
opaqueConstructionSecondaryIds.push(library?.slabOnGradeId);
return { opaqueConstructions: opaqueConstructionSecondaryIds || null };
};
I am calling above function in other place like as below
extractSecondaryIds: library => {
const secondaryIds = {
...extractSourceOfData(library),
...extractOpaqueConstructionType(library), // this is where i am calling above function
...extractGlazingConstructionType(library)
};
return secondaryIds;
},
if all the above id's for example(exteriorWallId, exteriorFloorId, etc...) are undefined, I am getting output from the above function (extractOpaqueConstructionType) like opaqueConstructions: [null] where as I am expecting like this opaqueConstructions: null if id's are undefined
Could any one please suggest any ideas or alternative approaches on this that would be very grateful to me, many thanks in advance.
It needs to filter the array after push all values.
Also you can simplify the code by simple remove the push calls
export const extractOpaqueConstructionType = library => {
const opaqueConstructions = [
library?.exteriorWallId,
library?.exteriorFloorId,
library?.roofId,
library?.interiorWallId,
library?.interiorFloorId,
library?.belowGradeWallId,
library?.slabOnGradeId,
].filter(it => it !== null);
return { opaqueConstructions: opaqueConstructions.length ? opaqueConstructions : null };
}
Try like below
export const extractOpaqueConstructionType = library => {
const opaqueConstructionSecondaryIds= [
library?.exteriorWallId
library?.exteriorFloorId,
library?.roofId,
library?.interiorWallId,
library?.interiorFloorId,
library?.belowGradeWallId,
library?.slabOnGradeId,
].filter(keyValue => keyValue!==undefine);
return { opaqueConstructions:opaqueConstructionSecondaryIds.length?
opaqueConstructionSecondaryIds : null };
};
I have an array containing one object of this form :
Array = [ { type: type, message: message } ]
I keep getting ESLint errors asking me to use object destructuring and array destructuring.
Currently my code looks like this :
let type=null;
let message=null;
if (data.length > 0) {
({ type, message } = data[0]);
}
So far this works and my variables are assigned correctly, however I am still getting the "Use array destructuring" message from ESLint.
Any help with this would be appreciated. Thank you
You can destructure the array:
let type=null;
let message=null;
if (data.length > 0) {
[{ type, message }] = data;
}
The code above is a shorter version of:
[ firstElement ] = data; // array destructruring
({ type, message } = firstElement); // object destructuring
Faly's way is good. You can also use default values when destructuring:
function test(label, data) {
// 1 -----------------------------vvvvv
let [{type = null, message = null} = {}] = data;
// 2 -----^^^^^^^---------^^^^^^^
console.log(label, type, message);
}
test("test1: ", []);
test("test2: ", [{type: "t"}]);
test("test3: ", [{type: "t", message: "m"}]);
That works because if data.length is 0, data[0] is undefined, and so triggers use of the default value {} (1) for the array part of that; within the object part of that, we use null (2) to handle any missing values on the object as well.
EsLint wants you to write
let type = null;
let message = null;
if (data.length > 0) {
[{ type, message }] = data;
}
which destructures the first item of an iterable data into the {type, message} target. (More items are ignored).
I would however recommend to use default values for the empty case:
const [{type, message} = {type:null, message:null}] = data;
or also
const [{type = null, message = null} = {}] = data;