Error when using usercentrics (via gtm) and id's in some components - javascript

we try to switch from our own implemented CMP to usercentrics. Therefore we integrated usercentrics via gtm on our page. I realized that the element is only shown on our subpages and is not visible on our root page.
After two days of removing and adding components again. I found out that usercentrics was able to load when I removed the id={"process"} from the component. I'm using multiple times the id tag for a smoothscroll plugin on our page. But only the one applied on the process and the one applied on the contact section are the ones that lead to the error below.
After I removed the plugin and nearly all id's beside one, I got the following error:
Uncaught TypeError: Cannot read property 'REACT_APP_SC_ATTR' of undefined
at bundle_legacy.js:1
at bundle_legacy.js:15
We're using a Gatsby Stack with Typescript and gatsby-plugin-smoothscroll for scrolling.
We implemented gtm via a Gatsby Plugin as well: gatsby-plugin-google-tagmanager
import React from "react";
import colors from "../../../../config/GlobalStyles";
import {Container, Grid, makeStyles, Typography} from "#material-ui/core";
// #ts-ignore
import infoGraphic from "../../../../images/root/process/infographic.webp";
import {graphql, useStaticQuery} from "gatsby";
import Markdown from "markdown-to-jsx";
const useStyles = makeStyles((theme) => ({
contentWrapper: {
paddingTop: "50px"
},
container: {
paddingTop: "50px",
backgroundColor: "white",
},
headline: {
fontWeight: 600,
color: colors.main
},
secondHeadline: {
fontFamily: "Mackay",
color: colors.main,
fontWeight: 400,
},
infoGraphicWrapper: {
overflow: "scroll",
[theme.breakpoints.down('sm')]: {
marginTop: "50px",
},
"& img": {
[theme.breakpoints.down('sm')]: {
maxWidth: "200%"
}
}
}
}));
export default function ProcessSection() {
const classes = useStyles();
const data = useStaticQuery(query);
return (
<section>
<Container className={classes.container}>
<Typography variant={"h2"} component={"h2"} className={classes.headline}>
<Markdown>
{data.strapiHome.process.headline}
</Markdown>
</Typography>
<Typography variant={"h2"} component={"h2"} className={classes.secondHeadline}>
<Markdown>
{data.strapiHome.process.secondHeadline}
</Markdown>
</Typography>
<Grid container className={classes.contentWrapper} justify={"space-between"}>
<Grid item xl={4} lg={4} md={4} sm={12} xs={12}>
<Typography component={"div"} variant={"body2"}>
<Markdown>{data.strapiHome.process.text}</Markdown>
</Typography>
</Grid>
<Grid item xl={7} lg={7} md={7} sm={12} xs={12} className={classes.infoGraphicWrapper}>
<img src={infoGraphic} alt={"alt text"} />
</Grid>
</Grid>
</Container>
</section>
);
}
const query = graphql`
query {
strapiHome {
process {
headline
secondHeadline
text
}
}
}
`;
I have no idea where this is coming from and what the env variables mean.

I think your problem is not in the code. To my point of view, it is related to the .env file.
If you are using process.env.REACT_APP_SC_ATTR somewhere, check the .env file to see if REACT_APP_SC_ATTR is defined.
.env file is like a global config. We normally add server url, port, production mode, things like this.

I was able to resolve the issue by removing all id's from my components and add some of them again.
I was not able to understand why this happened.

Related

The code is correct, but an img file stored locally is not displayed - React

On this project, I'm using the MUI library
I have an image on this route /assets/images/banner.png (I've already verified the route and the name of the image is the correct one) The code should be correctly showing me the "banner.png" but it isn't
This is my component HeroBanner.js
import React from 'react';
import { Box, Stack, Typography, Button} from '#mui/material';
import HeroBannerImage from '../assets/images/banner.png';
function HeroBanner() {
return (
<Box sx={{
mt: { lg:'212', xs:'70px' },
ml: { sm: '50px' }
}} position='relative' p='20px'>
<Typography color='#FF2625' fontWeight='600' fontSize='26px'>
Fitness Club
</Typography>
<Typography fontWeight={700}
sx={{ fontSize: { lg: '44px', xs:'40px'}}}>
Sweat, Smile <br /> and Repeat
</Typography>
<Typography fontSize='22px' lineHeight='35px' mb={3}>
Check out the most effective exercises
</Typography>
<Button variant='contained' color='error' href='#exercises'>Explore Exercise</Button>
<img src={HeroBannerImage} alt="hero-banner" className="hero-banner-img" />
</Box>
)
}
export default HeroBanner
I tried your code, and it worked for me. Maybe try importing another image or something. Make sure to check the folder names and image name.
This is the link for the tested code : Codesandbox
There are many options
here is a simple one
<img src={require('./path/to/image.svg').default} />

TestingLibraryElementError: Unable to find an element by: [data-testid="descriptive-slogan"]

I have written two tests in homePage.test.js file for testing my Home Page component. I'm using data-testid to get the dom node. Both the data-testid's are present in my dom. When I run tests first test runs successfully but the second one shows the above-mentioned error.
homePage.test.js
import { render, screen } from "#testing-library/react";
import '#testing-library/jest-dom'
import Home from "../src/pages/index"
render(<Home />)
test("main slogan", () => {
const text = /^Create Beautiful Coversfor blogs like a pro😎/
expect(screen.getByTestId('main-slogan')).toHaveTextContent(text);
})
test("descriptive slogan", () => {
const text = /^We at Cover Builders are aimed to provide you simple and easy tools, that helps you in generating blog covers easily/
expect(screen.getByTestId("descriptive-slogan")).toHaveTextContent(text);
})
Home Page component
import { Box, Typography } from "#mui/material";
import Image from "next/image";
import editorGif from "../../public/editorGif.gif"
export default function Home() {
return (
<Box className="homepage-gradient" sx={{ gridColumnStart: '1', gridColumnEnd: '4', color: 'white' }}>
<Box sx={{ display: 'flex', padding: '6rem 4rem', width: '100%', height: '100%', gap: 4 }}>
<Box sx={{ width: '60%', }}>
<Typography data-testid="main-slogan" sx={{ fontSize: '3rem', fontWeight: 'fontWeightBold' }}>
Create Beautiful Covers<br />
for blogs like a pro😎
</Typography>
<Typography data-testid="descriptive-slogan" sx={{ padding: '2rem 0', fontSize: '1.2rem' }}>
We at Cover Builders are aimed to provide you simple and easy tools,<br />
that helps you in generating blog covers easily.
</Typography>
</Box>
<Box sx={{ width: '40%', }}>
<Image
src={editorGif}
alt="full_editor"
style={{ borderRadius: '10px', margin: '0 0 0 2rem', }}
>
</Image>
</Box>
</Box>
</Box>
)
}
Update your test file accordingly,
If you are still in confusion, I have put your test file here,
I ran it and it worked.
https://github.com/YamatoDX/testing-practice-next/blob/testing/__tests__/Stack.test.tsx
import { render, screen } from "#testing-library/react";
import '#testing-library/jest-dom' // may be you don't need to import this
import Home from "../src/pages/index"
test("main slogan", () => {
render(<Home />);
const text = /^Create Beautiful Coversfor blogs like a pro😎/;
expect(screen.getByTestId("main-slogan")).toHaveTextContent(text);
});
test("descriptive slogan", () => {
render(<Home />);
const text =
/^We at Cover Builders are aimed to provide you simple and easy tools,that helps you in generating blog covers easily./i;
expect(screen.getByTestId("descriptive-slogan")).toHaveTextContent(text);
});

Warning: encountered two children with the same key, is appearing as an error in my REACT app

I'm in the process of building out a simple react act that display REST data from my localhost URL.
I keep getting this error and I'm not sure why, at first I thought it was the data within the API itself but I think that's not the case for this?
I am not getting any npm start errors, the error appears when I inspect a page with browser tools.
Here is the full error:
index.js:1 Warning: Encountered two children with the same key, `1`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.
at div
at Grid (http://localhost:4000/static/js/0.chunk.js:1556:35)
at WithStyles(ForwardRef(Grid)) (http://localhost:4000/static/js/0.chunk.js:6385:31)
at main
at Container (http://localhost:4000/static/js/0.chunk.js:1101:23)
at WithStyles(ForwardRef(Container)) (http://localhost:4000/static/js/0.chunk.js:6385:31)
at UserBuckets (http://localhost:4000/static/js/main.chunk.js:363:5)
at LoadingComponent (http://localhost:4000/static/js/main.chunk.js:999:5)
at div
at App (http://localhost:4000/static/js/main.chunk.js:173:89)
at Route (http://localhost:4000/static/js/0.chunk.js:48473:29)
at Switch (http://localhost:4000/static/js/0.chunk.js:48675:29)
at Router (http://localhost:4000/static/js/0.chunk.js:48108:30)
at BrowserRouter (http://localhost:4000/static/js/0.chunk.js:47728:35)
Could someone point out what is causing this error in my code? I haven't been able to solve it myself.
Here is my required code:
App.js
import React, { useEffect, useState } from 'react';
import './App.css';
import UserBuckets from './components/BucketLists';
import LoadingComponent from './components/Loading';
function App() {
const ListLoading = LoadingComponent(UserBuckets);
const [appState, setAppState] = useState({
loading: false,
buckets: null,
});
useEffect(() => {
setAppState({ loading: true });
const apiUrl = `http://127.0.0.1:8000/api/`;
fetch(apiUrl)
.then((data) => data.json())
.then((buckets) => {
setAppState({ loading: false, buckets: buckets });
});
}, [setAppState]);
return (
<div className="App">
<h1>Latest Buckets</h1>
<ListLoading isLoading={appState.loading} buckets={appState.buckets} />
</div>
);
}
export default App;
bucketList.js
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Card from '#material-ui/core/Card';
import CardContent from '#material-ui/core/CardContent';
import CardMedia from '#material-ui/core/CardMedia';
import Grid from '#material-ui/core/Grid';
import Typography from '#material-ui/core/Typography';
import Container from '#material-ui/core/Container';
const useStyles = makeStyles((theme) => ({
cardMedia: {
paddingTop: '56.25%', // 16:9
},
link: {
margin: theme.spacing(1, 1.5),
},
cardHeader: {
backgroundColor:
theme.palette.type === 'light'
? theme.palette.grey[200]
: theme.palette.grey[700],
},
bucketTitle: {
fontSize: '16px',
textAlign: 'left',
},
bucketText: {
display: 'flex',
justifyContent: 'left',
alignItems: 'baseline',
fontSize: '12px',
textAlign: 'left',
marginBottom: theme.spacing(2),
},
}));
const UserBuckets = (props) => {
const { buckets } = props;
const classes = useStyles();
if (!buckets || buckets.length === 0) return <p>Can not find any buckets, sorry</p>;
return (
<React.Fragment>
<Container maxWidth="md" component="main">
<Grid container spacing={5} alignItems="flex-end">
{buckets.map((buckets) => {
return (
// Enterprise card is full width at sm breakpoint
<Grid item key={buckets.owner} xs={12} md={4}>
<Card className={classes.card}>
<CardMedia
className={classes.cardMedia}
image="https://source.unsplash.com/random"
title="Image title"
/>
<CardContent className={classes.cardContent}>
<Typography
gutterBottom
variant="h6"
component="h2"
className={classes.bucketTitle}
>
{buckets.name.substr(0, 50)}...
</Typography>
<div className={classes.bucketText}>
<Typography
component="p"
color="textPrimary"
></Typography>
<Typography variant="p" color="textSecondary">
{buckets.stock_list}...
</Typography>
</div>
</CardContent>
</Card>
</Grid>
);
})}
</Grid>
</Container>
</React.Fragment>
);
};
export default UserBuckets;
Loading.js
import React from 'react';
function LoadingComponent(Component) {
return function LoadingComponent({ isLoading, ...props }) {
if (!isLoading) return <Component {...props} />;
return (
<p style={{ fontSize: '25px' }}>
We are waiting for the data to load!...
</p>
);
};
}
export default LoadingComponent;
Thank in advance...
The error came from this culprit and my mistake not seeing the important of the letter key in item key. This is how I solved my error:
original code
<Grid item key={buckets.owner} xs={12} md={4}>
fixed code
<Grid item key={buckets.id} xs={12} md={4}>

Problems with React Router/Hoook

Update (new changes):
So now I pretty much converted my code to a functional component however it is as if nothing is being returned from the API, or perhaps I am not "mounting" correctly? I get the error " TypeError: Cannot read property 'map' of undefined" meaning nothing is being returned but I'm not sure why. Help?
Old post (I had previously tried to use a hook in a a class component):
I'm pretty brand new to react and recently I have been getting this error from when trying to navigate to a page on click of a card media (using material ui). So I pretty much follow the instruction to push to history the route to the page I want to navigate to via a function and call that function when I click the media card. Below is my code and the error I get. Do you have any idea why I might be having an issue with this?
My updated code
import Card from '#material-ui/core/Card';
import CardMedia from '#material-ui/core/CardMedia';
import Grid from '#material-ui/core/Grid';
import Container from '#material-ui/core/Container';
import {getItems} from "../Network/network_utility";
import {useHistory} from "react-router-dom";
import {makeStyles} from '#material-ui/core/styles';
import React, {useState, useEffect} from "react";
const useStyles = makeStyles(theme => ({
icon: {
marginRight: theme.spacing(2),
},
heroContent: {
padding: theme.spacing(8, 0, 6),
},
cardGrid: {
paddingTop: theme.spacing(6),
paddingBottom: theme.spacing(3),
position: "fixed"
}
}));
export default function Items() {
let history = useHistory();
const classes = useStyles();
const useFeaturedItems = () => {
const [featured_items, setFeaturedItems] = useState([]);
useEffect(() => {
getItems(1).then(response => setFeaturedItems(response["data"]))}, []);
return featured_items;
};
return (
<div>
<Container className={classes.cardGrid} maxWidth="lg">
<Grid container spacing={6}>
{useFeaturedItems().map((card, index) => (
<Grid item key={index} xs={16} sm={4} md={2}>
<Card raised={false} style={{height: "30vh", width: "20vh"}}>
<CardMedia
component="img"
src={card["thumbnail"]}
style={{height: "25vh", width: "20vh"}}
onClick={history.push("/item")}
>
</CardMedia>
<div style={{paddingLeft: "10px", paddingTop: "10px"}}>
<text style={{
whiteSpace: "nowrap",
overflow: "hidden",
display: "block",
textOverflow: "ellipsis"
}}>
{card["title"]}
</text>
</div>
</Card>
</Grid>
))}
</Grid>
</Container>
</div>
);
}
As I can see you are using hook inside a class component. It is not possibile
how use hook
You can’t use Hooks inside a class component, but you can definitely mix classes and function components with Hooks in a single tree. Whether a component is a class or a function that uses Hooks is an implementation detail of that component. In the longer term, we expect Hooks to be the primary way people write React components.
In class component you need to use the HOC withRouter. After that you can access the history through props with this.props.history

Beginner Confusion: Four Quadrant Selection Grid in a Pop-Up Form Using Material UI & React

I apologize if these questions come off as dumb. I'm trying to jump into React & Material-UI and I don't have a mentor to ask questions to or guide me. Kind of shooting in the dark as I go using documentation and tutorials etc. I have a lot of questions..
(in fact is there a better place to ask these sorts of quick one-off questions? a beginners chat forum maybe? a Slack group? not sure if Stack is the best place for this..)
I'm building out a form for a client. One of the questions is a four quadrant chart where the user selects an option that combines 4 different vectors. It's hard to explain, and I'm not sure what the technical term is for this type of chart, so I drew a diagram to make it clear what I'm trying to achieve:
I started building out a component in React to handle this selection chart, but I'm already getting kind of lost.. Here is what I have so far...
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardActions from '#material-ui/core/CardActions';
import CardContent from '#material-ui/core/CardContent';
import CardMedia from '#material-ui/core/CardMedia';
import Button from '#material-ui/core/Button';
import Typography from '#material-ui/core/Typography';
import Grid from '#material-ui/core/Grid';
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
},
h2: { //<-- is there a better way to do this? Or do I need to target each h2 with a className classes.h2 ?
color: "#f00",
},
paper: {
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
},
card: {
maxWidth: 345,
},
media: {
height: 140,
},
}));
export default function ProjectMap() {
const classes = useStyles();
function Slow_Expensive() {
return (
<Card className={classes.card}>
<CardActionArea>
<CardContent>
<Typography variant="body2" color="textSecondary" component="p">
Selection box slow but expensive.
</Typography>
</CardContent>
</CardActionArea>
</Card>
);
}
function TopRow() {
return (
<React.Fragment>
<Grid item xs={4}></Grid>
<Grid item xs={4}>
<h2>Expensive</h2>
</Grid>
<Grid item xs={4}></Grid>
</React.Fragment>
);
}
function MidRow() {
return (
<React.Fragment>
<Grid item xs={4}>
<h2 className={classes.h2}>Slow</h2> {/*Do I need to set a className on all of my h2's or is there a better way to target all of them within this component. */}
</Grid>
<Grid item xs={4}>
<h2>The Four Quadrants go here.. maybe cards assembled into maybe another grid?? a table??</h2>
</Grid>
<Grid item xs={4}>
<h2>Fast</h2>
</Grid>
</React.Fragment>
);
}
function BotRow() {
return (
<React.Fragment>
<Grid item xs={4}></Grid>
<Grid item xs={4}>
Cheap
</Grid>
<Grid item xs={4}></Grid>
</React.Fragment>
);
}
return (
<div className={classes.root}>
<h2>Choose one of hte options:</h2>
<Grid container spacing={1}> {/*is grid the best way to layout this component? Should I use a table instead?*/}
<Grid container justify="center" item xs={12} spacing={2}>{/* Justify is not working.. I don't know why?*/}
<TopRow />
</Grid>
<Grid container justify="center" item xs={12} spacing={2}>
<MidRow />
</Grid>
<Grid container justify="center" item xs={12} spacing={2}>
<BotRow />
</Grid>
</Grid>
</div>
);
}
I'm still learning how Material-UI's Grid works. I come from a
traditional vanilla JS/CSS/HTML background, and back in the day we
used to use tables to lay out little widgets like this. In my code
above I'm attempting to build out a table layout using the
responsive grid system in Material-UI. Is this dumb? Or am I on the
right track? Is grid used for little components like this? Or is it
meant for larger layout elements like menus and page containers?
I'm attempting to use cards for the four quadrants, but how would I
assemble these into my larger grid? Do I need to nest another grid
inside the larger grid? Or should I be using some sort of grid
rowSpan or colSpan? Do grids even do that?
I was thinking about using react radio boxes and styling them like
divs since that would handle the click/select functionality, but I
settled on using "Cards" and just using javascript to make them like
radio boxes on click.
I don't fully understand how useStyles hook is used here. I know
it's meant to overrride the Material-UI component styles, but am I
supposed to use it for everything? For example I'm using tags
for the chart labels since semantically they seem to be chart
headings, but to style them, do I need to add them to my useStyles
function, and then add a className={classes.h2} to ALL of my H2's?
Seems like there must be a better way to style these elements
globally within my chart component. Should I be simply using a CSS
template attached to my component instead? like : import
'./Chart.css';?
Each of my other Components in this project also use "useStyles" but
I noticed some of them work, some of them don't. For example I tried
to resize a dialogue box to 80% width, but when I tried to apply it
to my dialogue box using className={classes.dialogue}, the styles
would not apply. I ended up using maxWidth = {'md'} property to get
it to stretch wider, but is that the best way to do that?
s
<Dialog className={classes.root}
open={this.state.dialogOpen}
onClose={this.onDialogClose}
maxWidth = {'md'}
>
Let me know your thoughts.. any tips or suggestions on which way to go with these issues would be greatly appreciated.
Thanks!
Do you need to support Internet Explorer? If not, easiest way to achieve this is using css grid.
Here is a example:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Card from "#material-ui/core/Card";
import CardContent from "#material-ui/core/CardContent";
import Typography from "#material-ui/core/Typography";
import Paper from "#material-ui/core/Paper";
const useStyles = makeStyles({
paper: {
display: "grid",
gridTemplateColumns: "3rem 250px 250px 3rem",
gridTemplateRows: "3rem 250px 250px 3rem",
gridGap: "1rem",
justifyItems: "center",
alignItems: "center",
justifyContent: "center"
},
top: {
gridRow: "1 / 2",
gridColumn: "1 / 5"
},
bottom: {
gridRow: "4 / 5",
gridColumn: "1 / 5"
},
left: {
gridRow: "2 / 4",
gridColumn: "1 / 2"
},
right: {
gridRow: "2 / 4",
gridColumn: "4 / 5"
},
card: {
width: "100%",
height: "100%"
}
});
function MyCard({ title }) {
const classes = useStyles();
return (
<Card className={classes.card}>
<CardContent>
<Typography>{title}</Typography>
</CardContent>
</Card>
);
}
function Quadrants() {
return (
<React.Fragment>
<MyCard title="Slow but expensive" />
<MyCard title="Fast but expensive" />
<MyCard title="Slow but Cheap" />
<MyCard title="Slow but Fast" />
</React.Fragment>
);
}
function FourQuadrants() {
const classes = useStyles();
return (
<Paper className={classes.paper}>
<Typography className={classes.top}>Expensive</Typography>
<Typography className={classes.bottom}>Cheap</Typography>
<Typography className={classes.left}>Slow</Typography>
<Typography className={classes.right}>Fast</Typography>
<Quadrants />
</Paper>
);
}
export default FourQuadrants;
Live example:

Categories