React Fetch API Being Called 2 Times on page load - javascript

React Fetch API Being Called 2 Times on page load, I don't know what is missing in this code or what I am doing wrong. I have faced this problem from the morning,
I really appreciate any help you can provide.
React Fetch API Being Called 2 Times on page load, I don't know what is missing in this code or what I am doing wrong. I face this problem from the morning,
I really appreciate any help you can provide.
import React, { useState, useEffect } from 'react'
import axios from 'axios';
import { Grid, Paper, TextField } from '#mui/material'
import PersonOutlineIcon from '#mui/icons-material/PersonOutline';
function FormApi() {
//Mui fileds and paper style
const paperStyle = { padding: '50px ', width: 550, margin: '50px auto' }
//Fetch data from api
const [userx, setUserx] = useState([{data:null,support:null}]);
const url = 'https://reqres.in/api/users/2';
useEffect(()=>{
//debugger
const fetchData = async () =>{
await axios.get(`${url}`)
.then((response) =>{
setUserx(response.data)
}).catch((error)=>{
console.log(error)
})
}
fetchData();
}
,[]);
return (
<Grid container spacing={2} style={paperStyle}>
<Grid align='center' >
<Paper elevation={20} >
<Grid align='center'>
<h2 style={{padding:'10px' ,background: "#000080", color: 'white' }}>
<PersonOutlineIcon large style={{fontSize:'80%'}} />User Details</h2>
</Grid>
<form>
<img style={{width:"20%"}} src={userx.data ? userx.data.avatar : ''}/>
<h1 style={{color:'#000080'}}>{userx.data ? userx.data.first_name : ''}
{userx.data ? userx.data.last_name : ''}</h1>
<Grid container >
<Grid item xs={6} >
<h2 style={{color:'white', background: "purple"}}>Contact Info</h2>
<TextField value={userx.data ? userx.data.id : ''} variant="standard"
/>
<TextField value={userx.data ? userx.data.email : ''}
variant="standard" />
</Grid>
<Grid item align='left' xs={6} style={{marginBottom:'40px'}}>
<h2 style={{color:'white', background: "purple"}}>Social Link</h2>
<TextField value={userx.support ? userx.support.url : ''}
variant="standard" />
<TextField value={userx.support ? userx.support.text : ''}
variant="standard" />
</Grid>
</Grid>
</form>
</Paper>
</Grid>
</Grid>
)
}enter code here
export default FormApi

It's because React renders components 2 times in the development environment. To avoid this, you can comment out the <React.StrictMode> tag in index.js file.
Rendering twice will only appear in the development environment and StrictMode has many benefits for development:
Identifying components with unsafe lifecycles
Warning about legacy string ref API usage
Warning about deprecated findDOMNode usage
Detecting unexpected side effects
Detecting legacy context API
Ensuring reusable state
So it's better to keep the <React.StrictMode> tag if it doesn't affect your normal development work.
See also: React StrictMode

This is normal behaviour in React 18. It will only be done on development environments and when StrictMode is enabled and will not be a problem in your production Build.
A bit annoying, but nothing really to worry about. There is a workaround which you can learn more about in a in-depth answer here:
React 18, useEffect is getting called two times on mount

You can handle it with useRef hook:
const renderAfterCalled = useRef(false);
useEffect(() => {
if (!renderAfterCalled.current) {
// your API call func
}
renderAfterCalled.current = true;
}, []);

as much as I know, this issue is caused by the HTTTP client sending 2 request, one to the route path "/" and the other to "/favicon.ico"
make this change :
useEffect(()=>{
checkLocation();
//your code
,[]);

after some revision
try this
function FormApi() {
//Mui fileds and paper style
const paperStyle = { padding: '50px ', width: 550, margin: '50px auto' }
//Fetch data from api
const [userx, setUserx] = useState([{data:null,support:null}]);
const url = 'https://reqres.in/api/users/2';
//debugger
const fetchData = async () =>{
await axios.get(`${url}`)
.then((response) =>{
setUserx(response.data)
}).catch((error)=>{
console.log(error)
})
}
useEffect(()=>{
fetchData();
}
,[]);

Related

how to set character limit to MUI autocomplete?

hey guys i've created an auto complete with material ui and api
i want to set limit on it so whenever the user types 3 letters,the autocomplete return matched suggestions
can anyone please help?
heres my code bellow:
import TextField from '#mui/material/TextField';
import Stack from '#mui/material/Stack';
import Autocomplete from '#mui/material/Autocomplete';
import { useEffect, useState } from 'react';
import { Box } from '#mui/system';
export default function Demo() {
const url = 'https://www.balldontlie.io/api/v1/players'
const [jsonResult,setJsonResult] = useState([]);
useEffect(()=>{
fetch(url)
.then((res) => res.json())
.then((json)=> setJsonResult(json.data));
},[]);
console.log('players',jsonResult);
return (
<Stack spacing={2} sx={{width:300}}>
<Autocomplete
id="free-solo-demo"
freeSolo
getOptionLabel={(jsonResult)=> `${jsonResult.first_name} ${jsonResult.last_name}`}
options={jsonResult}
isOptionEqualToValue={(option,value)=>
option.first_name === value.first_name
}
noOptionsText={"No Match Found"}
renderOption={(props,jsonResult)=>(
<Box component="li" {...props} key={jsonResult.id}>
{jsonResult.first_name} {jsonResult.last_name}
</Box>
)}
renderInput={(params)=>
<TextField {...params} label="Player search"/>
}
/>
</Stack>
);
}
i coulnd find any idea but any tutorial links is appreciated.
You can add this to your input field:
inputProps={{
maxLength: 3
}}
you can use a mask like this :
export default function FormattedInputs() {
const [values, setValues] = React.useState<State>({
textmask: '(100) 000-0000',
});
https://mui.com/material-ui/react-text-field/

Uncaught TypeError: Cannot read properties of undefined (reading '8')

This is my first time posting and I am a junior Frontend developer so please go easy on me.
This has me very confused and I've looked, tested and for some reason the Inputlabel from Material UI (ver. 5) is not working on this side of the website I am developing. I used inputlabel and date picker on the home page and they work with no problems. But suddenly trying to make a user profile form... Well, it's starting to give me trouble. Literally copying what is in the documentation and still get this issue.
When I click on the Input everythig on the page disappears. Opening the Chrome Inspector gives me the error that's in the title. And I am truly clueless. Posting my code to see if someone cand lend me a bit of help here. Thank you in advance.
import React from 'react';
import { TextField } from '#mui/material';
import { Grid } from '#mui/material';
import { Box } from '#mui/system';
import { Container } from '#mui/material';
import InputLabel from '#mui/material/InputLabel';
import MenuItem from '#mui/material/MenuItem';
import FormControl from '#mui/material/FormControl';
import Select from '#mui/material/Select';
import { DatePicker } from "#mui/lab";
import { LocalizationProvider } from "#mui/lab";
import AdapterDateFns from '#mui/lab/AdapterDateFns';
//import '../User/components/styles/UserStyles.scss';
const UserProfileTxt = () => {
//DOB picker
const [dob, setDob] = React.useState(new Date())
//Nationality Picker
const [nationality, setNationality] = React.useState('');
const handleChange = (event) => {
setNationality(event.target.value);
};
return (
<Container>
<Grid container>
<Grid sx={{ flexDirection: 'column', display: 'flex' }}>
<TextField sx={{mt:'0.5rem', mb:'0.5rem'}} variant='outlined' label='Nombre' />
<TextField sx={{mt:'0.5rem', mb:'0.5rem'}} variant='outlined' label='Apellido' />
<TextField sx={{mt:'0.5rem', mb:'0.5rem'}}variant='outlined' label='E-mail' />
<Box sx={{ minWidth: 120, mt:'0.5rem', mb:'1rem' }}>
<FormControl fullWidth>
<InputLabel id="NationalityUSERHIKLUB">Nacionalidad</InputLabel>
<Select
labelId="Nacionalidad"
id="Naccionalidad"
value={nationality}
label="Nationalidad"
onChange={handleChange}
>
<MenuItem value={1}>Ten</MenuItem>
</Select>
</FormControl>
</Box>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
label="Seleccióna fecha de Nacimiento"
value={dob}
onChange={(newValue) => {
setDob(newValue);
}}
renderInput={(params) => <TextField {...params} />}
/>
</LocalizationProvider>
</Grid>
<Grid>
</Grid>
</Grid>
</Container>
);
};
export default UserProfileTxt;
Okay. I solved my own question.
This is probably a bug, but I didn't add this to the original question because I seriously didn't think it was going to be related. Despite that, I am going to share it in case someone is having issues as well.
So, this form I am doing is inside a <Tabs/> component, which I costumized using <ThemeProvider/> and <CreateTheme/>. Started basically breaking my code down seeing where the error could stem from. Finally, I noticed that it could be the <ThemeProvider/> on the tabs. And sure enough, once I removed both <ThemeProvider/> and <CreateTheme/> The date picker and dropdown menu were working fine.
Sorry I didn't address it before but I seriously did not think it was going to be related to the issue at hand
So, long story short:
DO NOT USE THEMEPROVIDER WHEN USING TABS ON MUI VER 5. USE STYLED COMPONENTS INSTEAD AND GET THE SAME RESULT WITH A LOT LESS ISSUES. I suppose there is some sort of conflict with that and the tabs component.
Thanks to anyone who answered.

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

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.

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

filter table by value with react redux and firebase

I am trying to filter a table in a react component by a value inside a document in firebase.
The important code looks like this. Claims is being parsed into another component for the table rows.
class Claims extends Component {
componentDidMount() {
this.props.getClaims();
}
render() {
const { Claims, loading } = this.props.data;
let recentClaimsMarkup = !loading ? (
Claims.map(Claim => <ClaimsTable Claim={Claim} />)
) : (
<p>Loading...</p>
);
return (
<Grid>
<Paper className = {mergeClasses.root}>
<Typography> {this.props.match.params.Project} Claim's</Typography>{" "}
</Paper>
<Paper className={mergeClasses.root}>
<Table className={mergeClasses.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Claim ID</TableCell>
<TableCell align="right">Date received</TableCell>
<TableCell align="right">Progress</TableCell>
<TableCell>Edit Claim</TableCell>
</TableRow>
</TableHead>
<TableBody>{recentClaimsMarkup}</TableBody>
</Table>
</Paper>
I am wanting to filter it by the url Project, shown below
{this.props.match.params.Project}
This is due to the claims being tied to the project name.
If this was in Python I would just use a for loop or something similar, but a little bit confused how to filter what Claims are able to be mapped.
Basically want it to be, for claims with Project == {this.props.match.params.Project}: map claims.
Appreciate any help :)
Thanks
So basically filter also returns a new copy of array and you can read more here, but the problem is you can't create the jsx element, if you want to know more
you can read this question
so in your case you need to first filter and then you need to render the jsx element using map like shown below
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route } from "react-router-dom";
import "./styles.css";
const User = props => {
const claimsUserHasAccess = props.data.claims.filter(
claim => claim.project === props.match.params.access
);
return (
<>
{claimsUserHasAccess.map(claim => (
<p key={claim.name}>{claim.name}</p>
))}
</>
);
};
const userData = {
claims: [
{ project: "enabled", name: "job" },
{ project: "enabled", name: "nick" },
{ project: "disabled", name: "jef" }
]
};
function App() {
return (
<div className="App">
<BrowserRouter>
<Route
path="/user/:access"
render={props => <User data={userData} {...props} />}
/>
</BrowserRouter>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
in the url you need to enter enabled or disabled to see the users. I hope this will give a better view of your problem.
working codesandbox

Categories