How to run map function in Reactjs? - reactjs

How to run map function I am trying to map function but it throws error cannot read the property of map undefined in Reactjs
I'm trying to do something like the following in React JSX component
const data = {
Details: [
{
"id": "6f12",
"nextPart": {
"id": "1ae2",
"text": "Details",
"heading": "twice data and staff memeber",
"checks": [
{
"value": "A"
},
{
"value": "B"
}
],
"Types": "Error"
},
"conclusion": "final"
}
]
}

The nextPart property is an object, not an array. Map works on arrays.
If your Details is intended to be an array of objects (which looks like it does), you can do it like this
{data.Details.map((item) => {
const { text, heading, checks } = item.nextPart;
return (
<div>
<div>{text}</div>
<div>{heading}</div>
<div>
{checks.map(({ value }) => (
<div>{value}</div>
))}
</div>
</div>
);
})}

Related

Undefined error when rendering react component with data retrieved from GraphQL Apollo Client

I have the component above, which takes the ArtigoID params value from the URL and fetch it to a GraphQL endpoint.
const DadosDoArtigo = () => {
let { ArtigoID }: any = useParams();
const { data, loading } = useQuery<{ artigo: ArtigoParUsuariosInternos }>(
queryDadosArtigo,
{
variables: { ArtigoID: Number(ArtigoID) },
}
);
return (
<IceBgPanel>
<>
<SectionTitle>Dados do artigo</SectionTitle>
{data === undefined ? (
<p>Algum coisa para carregando</p>
) : (
<>
<p>Artigo aprovado</p>
<small>
{data.artigo.UltimaAcaoNoArtigo.Descricao === "Aprovado"
? "Sim"
: "Não"}
</small>
</>
)}
</>
</IceBgPanel>
);
};
My API is throwing only one request to run queryDadosArtigo and it gets the following object as response
{
"data": {
"artigo": [
{
"Titulo": "Teste",
"Tags": [
{
"NomeDaTag": "Callie Sampaio",
"TagID": 3,
"__typename": "ArticleTag"
},
{
"NomeDaTag": "Dale da Rocha",
"TagID": 5,
"__typename": "ArticleTag"
}
],
"Corpo": "<p>Chamado de teste</p>\n",
"HistoricoDoArtigo": [],
"VisivelParaTodosUsuarios": true,
"UltimaAcaoNoArtigo": {
"Descricao": "SavedInDevelopment",
"__typename": "TiposAcaoEmArtigo"
},
"__typename": "Artigo"
}
]
}
}
The problem is that when my React application tries to render the component, it breaks with a TypeError exception that says:
TypeError: data.artigo.UltimaAcaoNoArtigo is undefined
I can't understand why its undefined, since it actually has data that was retrieved by the GraphQL API.
The second this I can't get is: why the ternary operator didn't render the paragraph, since data was undefined?
Any guess why this is happening?

filter array in props

i keep having a problem with filtering an array of objects in props in a nextjs page. i m using below json and coding.
[
{
"id": "1",
"name": "name1",
"category": ["food"]
},
{
"id": "2",
"name": "name2",
"category": ["food", "beverages"]
}]
import React from "react";
const test2 = ({ prods }) => {
return (
<div>
<div>
{prods
.filter((product) => product.category.includes("eve"))
.map((filterarray) => (
<li>
{filterarray.id}
{filterarray.name}
{filterarray.category}
</li>
))}
</div>
</div>
);
};
export async function getStaticProps() {
const prods = (await import("./product.json")).default;
return {
props: {
prods,
},
};
}
export default test2;
listing the full array works. (data comes as 1 string eg 'foodbeverage' but that should still be ok i think)
Filtering on id works fine. But when i try to use include it no longer displays any result.
if anyone could point me to what i m doing wrong. or if i better follow a different approach, any help would be much appreciated.
You need to replace include with some on the category array:
let prods = [
{
id: "1",
name: "name1",
category: ["food"]
},
{
id: "2",
name: "name2",
category: ["food", "beverages"]
}
];
let result = prods.filter((product) =>
product.category.some((pro) => pro.includes("eve"))
);
console.log(result);
Array#includes() does not do partial matches. You need to use String#includes() on each element in the array.
You could do this by using Array#some() in the filter.
prods.filter((product) => product.category.some(cat=>cat.includes("eve")))

how do I Mock API and following the same approach as my static array?

I have a React hooks component, which uses an HTML div-alike table to render data, and the data is being fetched from the server. I need to test the component to see if the table has data by mocking the API call. Below is the current code. I want to remove the use of arr completely and make avoid getting {users} rendered as text/plain as you can you in the below image
const arr = [
{
"demo": [
{
"_id": "T0810",
"title": "Historian",
"tags": [
"demo"
],
"queries": [],
},
{
"_id": "T0817",
"title": "book",
"tags": [
"demo"
],
"queries": [],
},
],
"demo_2": [
{
"_id": "T0875",
"title": "Program",
"tags": [
"demo_2",
"Control"
],
"queries": [],
},
{
"_id": "T0807",
"title": "Interface",
"tags": [
"demo_2"
],
"queries": [],
}
]
}];
const keys = Object.keys(arr[0]);
export default function Demo () {
const [isModalOpen, setModalIsOpen] = useState(false);
const [users, setUsers] = useState([]);
const handleOnClick = async () => {
try {
const { data } = await axios.get('https://run.mocky.io/v3/0d7aa6e3-fc01-4a47-893d-7e1cc3013d4e');
setUsers(data);
// Now that the data has been fetched, open the modal
setModalIsOpen(true);
} catch (err) {
console.error("failed", err);
}
};
return (
<div className="container">
<>
{keys.map((key) => (
<div className="col" key={key}>
<div className="row">{key}</div>
{arr[0][key].map((item) => (
<div className="row" key={item.technique_id} onClick={() => handleOnClick(item)}>{item.technique}</div>
))}
</div>
))}
</>
{isModalOpen && <Modal onRequestClose={() => setModalIsOpen(false)} data={users}/>}
</div>
);
}
Second attempt...Assuming I understand the ask then a package like Nock can do the trick (https://github.com/nock/nock).
The approach is to allow Nock to mock the API and return the result locally without calling the server. In your case it will be something like:
const nock = require('nock');
const arr = [...]; // your original definition of arr
const scope = nock('https://run.mocky.io')
.get('/v3/0d7aa6e3-fc01-4a47-893d-7e1cc3013d4e')
.reply(200, arr);
// The rest of your code "as is"
...
This setup of Nock will intercept every HTTP call to https://run.mocky.io and will specifically return the content of arr in response to a GET /v3/0d7aa6e3-fc01-4a47-893d-7e1cc3013d4e.
Typically, I would not put this code in the main code.
Instead you can use it as part of a testing script that runs without dependency on an active server. E.g. testing during build.

draftjs how to initiate an editor with content from an array object of html

I want to create an editor which will initiate an html element with the styling..
const contents = [
{
"text": "Sample text",
"HTML": "<p style='text-align: center;'><span style='font-size:3em;'><strong>Sample text</strong></span></p>"
},
{
"text": "Sample text2",
"HTML": "<p style='text-align: center;'><span style='font-size:3em;'><strong>Sample text2</strong></span></p>"
}
]
then I map it to get the html key then set it in the state
const content = contents.map(element => htmlToDraft(element.HTML))
this.state = {
editorState: EditorState.createWithContent(content)
}
Then rendering the editor multiple times by the number of elements of html key in the state:
this.state.editorState.map((element,index) => {
return
<Editor
defaultEditorState = {element}
onEditorStateChange = {this.onEditorStateChange}
key={index}
/>
})
When I run it, it throws an error contentState.getBlockMap is not a function

React, how to render static json data with different keys

Here's an example of the static json data.
I'm having trouble rendering the 'promoimage' from the array.
I'm not 100% sure how to go about this to solve it. I was playing arround and wanted to check if 'promoimage' exists, but nothing was returned?
Any advice how to achieve this?
[
{
"title": "some title",
"promoimage": "image.jpg",
"url": "#"
},
{
"title": "some title",
"image": "example.jpg",
"url": "#"
},
{
"title": "some other title",
"promoimage": "image.jpg",
"url": "#"
},
{
"title": "title",
"image": "example.jpg",
"url": "#"
},
]
My React component:
import products from '../product-data.json';
...
export const CustomSlider = () => {
// Here I'm using react-slick
const productList = products.map((product, i) => {
const uniqueItems = [];
if (uniqueItems.indexOf(product.imageone) === -1) {
uniqueItems.push(product.imageone);
}
/* This works
if (product.hasOwnProperty('promoimage')) {
return true
}
*/
return <Product key={i} {...product} />;
}
);
return (
<Slider>
{productList}
</Slider>
)
}
The code is sending all object keys to Product, as props. Particularly this part {...product} is expanded into this:
<Product
key={i}
title="some title"
promoimage="image.jpg"
url="#"
/>
This is called spreading.
Now, I suspect <Product> doesn't know what to do with promoimage, but knows what to do with image. We haven't sent any image so we have to fix that. We can do so by either modifying product so that it renders image || promoimage, or change our parsing to this:
const productList = products.map((product, i) => {
const uniqueItems = []
if (uniqueItems.indexOf(product.promoimage) === -1) {
uniqueItems.push(product.promoimage)
}
return (
<Product
key={i}
{...product}
image={product.image || product.promoimage}
/>
)
})

Resources