React add label to nested array object in Object.keys map - javascript

I have a React component which is pulling JSON data via an axios.get call and then I am mapping an embedded object using the following function:
axios.get('MasterData.json').then(response => {
const fullTree = response.data.graph.tree;
const resultTree = Object.keys(fullTree).map(key => ({
...fullTree[key],
id: key
}));
This produces the following:
{5bd356cc-5ee6-49a0-ab68-65cbf0209105: Array(6), id: "5bd356cc-5ee6-49a0- ab68-65cbf0209105"}
which is great, but I need to add a label of "ports: to the entire nested array (Array(6)) that is being output above so that I can map it. Any help is appreciated.

axios.get('MasterData.json').then(response => {
const fullTree = response.data.graph.tree;
console.log(fullTree) // you must check this fist
const resultTree = Object.keys(fullTree).map(key =>
new Port({ // create some function to generate get port as you want
port : fullTree[key],
id: key
)
});
for create function maybe on bellow me can explain more :)

Related

Map function to build an array from filtered object

I'm trying to get my head around map functions currently without much success.
I currently have a list of objects and am trying to remap to a new object using the map function to return a map indexed by the created property with a list of wooids.
Having written my map function, I only seem to be returning the last time.
const variants = [
{
created: '2022-03-06',
hashname: 'c78ba80402290724609a5e98c369c90984494152',
hashobject: '80864e6329d5e305a512ace872ad7d56a3f41095',
hashparent: '19c5d50ddddeb7c9a92469df78c47d9d611f1599',
action: 'added',
wooid: 7288
},
{
created: '2022-03-06',
hashname: 'c78ba80402290724609a5e98c369c90984494152',
hashobject: '80864e6329d5e305a512ace872ad7d56a3f41095',
hashparent: '19c5d50ddddeb7c9a92469df78c47d9d611f1599',
action: 'added',
wooid: 7289
}
]
const res = Object.fromEntries(variants.map(k => [k.created, [k.wooid]]))
console.log(res)
Current output
{ '2022-03-06': [ 7289 ] }
Desired output:
{ '2022-03-06': [ 7289, 7288 ] }
Any help would be greatly appreciated as I'm unsure how to dynamically populate the array to include all other entires (6 in total).
Use Array.prototype.reduce() to build up your object. Check if you already have a key for each created value and if not, create an empty array. Then append the wooid value
const variants = [{"created":"2022-03-06","hashname":"c78ba80402290724609a5e98c369c90984494152","hashobject":"80864e6329d5e305a512ace872ad7d56a3f41095","hashparent":"19c5d50ddddeb7c9a92469df78c47d9d611f1599","action":"added","wooid":7288},{"created":"2022-03-06","hashname":"c78ba80402290724609a5e98c369c90984494152","hashobject":"80864e6329d5e305a512ace872ad7d56a3f41095","hashparent":"19c5d50ddddeb7c9a92469df78c47d9d611f1599","action":"added","wooid":7289}]
const res = variants.reduce((acc, { created, wooid }) => ({
...acc,
[ created ]: [
...acc[created] ?? [], // init to an empty array if unset
wooid
]
}), {})
console.log(res)
This will collect wooid values by created in the order they appear in the original data.

Getting error of fetched items after refreshing the page

I am fetching my data from external API as usual and this is the typical way I do it:
Fetch API:
const [tshirts, setTshirts] = useState([]);
const fetchData = () => {
fetch('apiEndpoint')
.then((response) => response.json())
.then((data) => {
setTshirts(data[0].clothes.regular.top); // path to my array
})
.catch((error) => {
console.log(error);
});
};
React.useEffect(() => {
fetchData();
}, []);
Map through an array:
const tshirtArray = tshirts.tShirt; // specifying the path
const listItems = tshirtArray.map((item) => <li>{item}</li>);
<ul>{listItems}</ul>
Example of data structure:
[
{
id: 1,
clothes: {
regular: {
top: {
sleeveless: [],
tShirt: [
"image-path-here"
],
.....
.....
.....
When I first time execute the code it works, but after some time or after refreshing the page I get an error of TypeError: Cannot read properties of undefined (reading 'map')
Why is that undefined? The path is correct and fetching the array should be as well. Can not find the reason of it not working.
I don't have reputation to comment, so let me try to clarify it for you through an answer. As #sojin mentioned, you cannot use tshirts.Tshirt since your state is of array type and arrays can't be used like objects, meaning that if there was an object of lets say exampleObject = { type: "shirt", color: "white } you could call it with exampleObject.type. Since you have an array of objects in your state (top that you are saving to state is still object which contains tShirt array), you first have to use index (to tell which object you want to use from the state array) and then you can use it like you wanted. For example, in your example there are 1 objects in state array. Array indexes start at 0. So you could do tshirts[0].tShirt to get the tShirt array from that object.
However, I would edit your code a bit. Instead of using tshirtArray constant, just do listItems from your state:
const listItems = tshirts.map((item) => {item.tShirt[0]});
Note: I've just used index 0 here to demonstrate the finding of the first item in tShirt array. If you want to see all tShirt image paths, then you may need to do nested mapping or other similar solutions.

Why am I unable to map this array of objects when it is loaded in useState()?

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}

Why can't I use dot notation on React State?

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.

Using `map` to Create New Array of Objects with Fewer Properties

I am wanting to use map to create a new array of of objects that have two properties from the original objects in the originating array, so I am trying this:
const filteredConfigurableModules = configurableModules.map(module =>
module.name, module.configurables
);
But this isn't working, as only the "name" is saved to the new array. What am I missing here?
I also tried this:
const filteredConfigurableModules = configurableModules.map(module => {
name: module.name,
configurables: module.configurables
});
... but end up with a syntax error:
SyntaxError: Unexpected token ':'
As I see you want to map from one array to another. You can do it in 2 ways:
Inline
const filteredConfigurableModules = configurableModules.map(module => ({name: module.name, configurables: module.configurables}));
When you do inline and return an object you have to wrap it in parenthesis so that it gets evaluated properly.
Use Return Statement
const filteredConfigurableModules = configurableModules.map(module => {
return {
name: module.name,
configurables: module.configurables
};
});
You should wrap it with parentheses as follow:
const filteredConfigurableModules = configurableModules.map(({name, configurables})=> ({
name,
configurables
}));
You can create a new object on the arrow function from the map:
const filteredConfigurableModules = configurableModules.map(module =>
({ name: module.name, configurables: module.configurables })
);
this return an array of objects with name and module fields.
If you return an object, you need to use parenthesis because otherwise it will be treated as a code body with no return.
Can you try this if i understand your question correctly
const filteredConfigurableModules = configurableModules.map(module => ({
name : module.name,
configurables : module.configurables,
}));

Categories