I have this code:
const useStyles = makeStyles({
card: {
maxWidth: 345,
},
media: {
height: 140,
},
});
export default function AlbumCard(props) {
const classes = useStyles();
let artist
let albumName
let artistHead
albumName = props.album.name
artist = props.album.artists.map((name, key) => {
if(albumName != name.name) {
return <Typography variant="body2" color="textSecondary" component="p" key={key}>
{name.name}
</Typography>
}
})
artistHead = props.album.artists.length > 1 ? 'Artists:' : 'Artist:'
const album = props.album
const page = "https://open.spotify.com/album/" + album.id
return(
<Grid item md={3}>
<Card className={classes.card}>
<CardActionArea>
<CardMedia
className={classes.card}
component="img"
alt={album.name}
height="140"
width="100"
image={album.images[0].url}
title={album.name}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{album.name}
</Typography>
<Typography variant="body2" color="textSecondary" component="h3">
Release Date
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
{album.release_date}
</Typography>
<Typography variant="body2" color="textSecondary" component="h3">
{artistHead}
</Typography>
{artist}
<Typography variant="body2" color="textSecondary" component="p">
{!props.showMarkets && album.available_markets.map((c, i) => {
return <li key={i}>{c}</li>
})}
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
Album Page
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
<a href={album.uri}>Open In App</a>
</Typography>
</CardContent>
</CardActionArea>
<Button
size="small"
color="primary"
onClick={props.handleShow}
>{!props.showMarkets ? "Hide Markets" : "Show Markets"}</Button>
</Card>
</Grid>
)
}
This code is rendering by this high-order components:
class Album extends React.Component {
constructor(props) {
super(props)
this.state={
artistId: '',
albumName: '',
holeData: '',
marketsDisplay: true,
data: []
}
this.handleOnChange = this.handleOnChange.bind(this)
this.handleOnClick = this.handleOnClick.bind(this)
}
handleOnChange(e) {
e.preventDefault()
const target = e.target
const value = target.value
const name = target.name
this.setState({
[name]: value
})
}
handleAlert(e) {
e.preventDefault()
alert('Plead type the album name and/or artist id')
}
handleOnClick(e) {
e.preventDefault()
fetch('https://api.spotify.com/v1/artists/' + this.state.artistId + '/albums', {
"method": "GET",
"dataType": "json",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer " + this.props.access_token
}
})
.then(res => res.json())
.then((data) => {
this.setState({
holeData: data,
data: data.items
})
})
}
ToggleButton() {
this.setState((currentState) => ({
marketsDisplay: !currentState.marketsDisplay
}))
}
render() {
let albums
let albumList
let display
albumList = this.state.data.map((name, key) => {
return <AlbumCard
album={name}
showMarkets={this.state.marketsDisplay}
handleShow={() => this.ToggleButton()}
key={key}
/>
})
return(
<React.Fragment>
<CssBaseline />
<Container maxWidth="sm">
<Typography component="div" style={{backgroundColor: '#cfe8fc', marginTop: '5%', marginBottom: '5%'}}>
<FormControl fullWidth={true}>
<TextField
id="outlined-basic"
label="Artist ID"
variant="outlined"
type="text"
name="artistId"
value={this.state.artistId}
onChange={this.handleOnChange}>
</TextField>
<Button
type="button"
color="secondary"
onClick={this.state.artistId ? this.handleOnClick : this.handleAlert}>Getir</Button>
</FormControl>
</Typography>
</Container>
<Grid container spacing={6}>
{albumList}
</Grid>
</React.Fragment>
)
}
}
export default Album
In the end I have multiple cards. When I click the button of any card, I'm expecting open a list of JUST one card but happening is when I click any button, all card's lists are opening.
I couldn't achieve this problem.
I'm stuck so bad.
Pelase help me.
Thank you.
Well, I did it.
I created states from returning data from Spotify API and made the values false.
After, I created two functions. One is making the value true and the other false.
And finally I gave the functions to props of AlbumCard component as value.
Here is my codes last versions (also there are some other changes irrelevant with the issue):
Album.js
import React from 'react';
import CssBaseline from '#material-ui/core/CssBaseline';
import Typography from '#material-ui/core/Typography';
import Container from '#material-ui/core/Container';
import FormControl from '#material-ui/core/FormControl';
import Button from '#material-ui/core/Button';
import TextField from '#material-ui/core/TextField';
import AlbumCard from './Card';
import Grid from '#material-ui/core/Grid';
import SelectArtist from './SelectArtist'
class Album extends React.Component {
constructor(props) {
super(props)
this.state={
artistId: '',
artistName: '',
holeData: '',
artists: '',
showSelect: false,
marketsDisplay: true,
data: []
}
this.handleOnChange = this.handleOnChange.bind(this)
this.handleOnClick = this.handleOnClick.bind(this)
this.handleOnArtists = this.handleOnArtists.bind(this)
}
handleOnChange(e) {
e.preventDefault()
const target = e.target
const value = target.value
const name = target.name
this.setState({
[name]: value
})
}
handleAlert(e) {
e.preventDefault()
alert('Plead type the album name and/or artist id')
}
handleOnClick(e) {
e.preventDefault()
fetch('https://api.spotify.com/v1/artists/' + this.state.artistId + '/albums', {
"method": "GET",
"dataType": "json",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer " + this.props.access_token
}
})
.then(res => res.json())
.then((data) => {
let idObj={}
this.setState({
holeData: data,
data: data.items,
})
//create states with false value
//from returning data
data.items.map((name, key) => {
this.setState({
[name.id]: false
})
})
})
}
handleOnArtists(e) {
e.preventDefault()
fetch('https://api.spotify.com/v1/search?q=' + encodeURIComponent(this.state.artistName) + '&type=artist', {
"method": "GET",
"dataType": "json",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer " + this.props.access_token
}
})
.then(res => res.json())
.then((data) => {
this.setState({
artists: data.artists.items,
showSelect: true
})
})
}
//make the value true
ToggleOpen(event, type) {
this.setState({
[type]: true
})
}
//make the value false
ToggleClose(event, type) {
this.setState({
[type]: false
})
}
render() {
let albumList
let artists
let albumId
artists = <SelectArtist
artists={this.state.artists}
name="artistId"
artistId={this.state.artistId}
handleOnChange={this.handleOnChange}
showSelect={this.state.showSelect}
/>
albumList = this.state.data.map((name, key) => {
return <AlbumCard
album={name}
//give the states to AlbumCard component as props
showMarkets={this.state[name.id]}
//give the functions to AlbumCard component as props
handleShow={
this.state[name.id] ?
event => this.ToggleClose(event, name.id) :
event => this.ToggleOpen(event, name.id)
}
key={key}
/>
})
return(
<React.Fragment>
<CssBaseline />
<Container>
<Typography component="div" style={{marginTop: '5%', marginBottom: '5%'}}>
<FormControl fullWidth={true}>
<TextField
id="outlined-basic"
label="Artist Name"
variant="outlined"
type="text"
name="artistName"
value={this.state.artistName}
onChange={this.handleOnChange}>
</TextField>
<Button
variant="contained"
type="button"
color="primary"
onClick={this.state.artistName ? this.handleOnArtists : this.handleAlert}>Get Artists</Button>
{this.state.showSelect ? artists : null}
{
this.state.artistId ?
<Button
variant="contained"
type="button"
color="primary"
onClick={this.state.artistId ? this.handleOnClick : this.handleAlert}>
Get Albums
</Button> : null
}
</FormControl>
</Typography>
<Grid container spacing={6}>
{albumList}
</Grid>
</Container>
</React.Fragment>
)
}
}
export default Album
Card.js
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 Typography from '#material-ui/core/Typography';
import Grid from '#material-ui/core/Grid';
import Button from '#material-ui/core/Button';
const useStyles = makeStyles({
card: {
maxWidth: 345,
},
media: {
height: 140,
},
});
export default function AlbumCard(props) {
const classes = useStyles();
let artist
let albumName
let artistHead
albumName = props.album.name
artist = props.album.artists.map((name, key) => {
if(albumName != name.name) {
return <Typography variant="body2" color="textSecondary" component="p" key={key}>
{name.name}
</Typography>
}
})
artistHead = props.album.artists.length > 1 ? 'Artists:' : 'Artist:'
const album = props.album
const page = "https://open.spotify.com/album/" + album.id
return(
<Grid item md={3}>
<Card className={classes.card}>
<CardActionArea>
<CardMedia
className={classes.card}
component="img"
alt={album.name}
height="140"
width="100"
image={album.images[0].url}
title={album.name}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{album.name}
</Typography>
<Typography variant="body2" color="textSecondary" component="h3">
Release Date:
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
{album.release_date}
</Typography>
<Typography variant="body2" color="textSecondary" component="h3">
{artistHead}
</Typography>
{artist}
<Typography variant="body2" color="textSecondary" component="p">
{props.showMarkets && album.available_markets.map((c, i) => {
return <li key={i}>{c}</li>
})}
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
Album Page
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
<a href={album.uri}>Open In App</a>
</Typography>
</CardContent>
</CardActionArea>
<Button
size="small"
color="primary"
onClick={props.handleShow}
>{props.showMarkets ? "Hide Markets" : "Show Markets"}</Button>
</Card>
</Grid>
)
}
I guess I'll be never a good narrator but hope some others find my solution helpful
Related
Currently working on a social media type app for class, but came across some issues grabbing values from user object.
friends is set to be an empty array. None of the other values destructered appear when passing the variable they are assigned too. want to know why the user is not getting set to data in the getUser function.
import {
ManageAccountsOutlined,
EditOutlined,
LocationOnOutlined,
WorkOutlineOutlined,
} from "#mui/icons-material";
import { Box, Typography, Divider, useTheme } from "#mui/material";
import UserImage from "../../components/UserImage";
import FlexBetween from "../../components/FlexBetween";
import WidgetWrapper from "../../components/WidgetWrapper";
import { useSelector } from "react-redux";
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
const UserWidget = ({ userId, picturePath }) => {
const [user, setUser] = useState(null);
const { palette } = useTheme();
const navigate = useNavigate();
const token = useSelector((state) => state.token);
const dark = palette.neutral.dark;
const medium = palette.neutral.medium;
const main = palette.neutral.main;
const getUser = async () => {
const response = await fetch(`http://localhost:3001/users/${userId}`, {
method: "GET",
headers: { Authorization: `Bearer ${token}` },
});
const data = await response.json();
setUser(data);
};
useEffect(() => {
getUser();
}, []); // eslint-disable-line react-hooks/exhaustive-deps
if (!user) {
return null;
}
const {
firstName,
lastName,
location,
occupation,
viewedProfile,
impressions,
friends
} = user;
return (
<WidgetWrapper>
{/* FIRST ROW */}
<FlexBetween
gap="0.5rem"
pb="1.1rem"
onClick={() => navigate(`/profile/${userId}`)}
>
<FlexBetween gap="1rem">
<UserImage image={picturePath} />
<Box>
<Typography
variant="h4"
color={dark}
fontWeight="500"
sx={{
"&:hover": {
color: palette.primary.light,
cursor: "pointer",
},
}}
>
{firstName} {lastName}
</Typography>
<Typography color={medium}>{friends.length} friends</Typography>
</Box>
</FlexBetween>
<ManageAccountsOutlined />
</FlexBetween>
<Divider />
{/* SECOND ROW */}
<Box p="1rem 0">
<Box display="flex" alignItems="center" gap="1rem" mb="0.5rem">
<LocationOnOutlined fontSize="large" sx={{ color: main }} />
<Typography color={medium}>{location}</Typography>
</Box>
<Box display="flex" alignItems="center" gap="1rem">
<WorkOutlineOutlined fontSize="large" sx={{ color: main }} />
<Typography color={medium}>{occupation}</Typography>
</Box>
</Box>
<Divider />
{/* THIRD ROW */}
<Box p="1rem 0">
<FlexBetween mb="0.5rem">
<Typography color={medium}>Who's viewed your profile</Typography>
<Typography color={main} fontWeight="500">
{viewedProfile}
</Typography>
</FlexBetween>
<FlexBetween>
<Typography color={medium}>Impressions of your post</Typography>
<Typography color={main} fontWeight="500">
{impressions}
</Typography>
</FlexBetween>
</Box>
<Divider />
{/* FOURTH ROW */}
<Box p="1rem 0">
<Typography fontSize="1rem" color={main} fontWeight="500" mb="1rem">
Social Profiles
</Typography>
<FlexBetween gap="1rem" mb="0.5rem">
<FlexBetween gap="1rem">
<img src="../assets/twitter.png" alt="twitter" />
<Box>
<Typography color={main} fontWeight="500">
Twitter
</Typography>
<Typography color={medium}>Social Network</Typography>
</Box>
</FlexBetween>
<EditOutlined sx={{ color: main }} />
</FlexBetween>
<FlexBetween gap="1rem">
<FlexBetween gap="1rem">
<img src="../assets/linkedin.png" alt="linkedin" />
<Box>
<Typography color={main} fontWeight="500">
Linkedin
</Typography>
<Typography color={medium}>Network Platform</Typography>
</Box>
</FlexBetween>
<EditOutlined sx={{ color: main }} />
</FlexBetween>
</Box>
</WidgetWrapper>
);
};
export default UserWidget;
const {
firstName,
lastName,
location,
occupation,
viewedProfile,
impressions,
friends
} = user;
store all your data from fetch inside of useState
make it useState({your object})
Don't do this:
if (!user) {
return null;
}
const {
firstName,
lastName,
location,
occupation,
viewedProfile,
impressions,
friends
} = user;
istead do:
const [user, setUser] = useState({});
const getUser = async () => {
const response = await fetch(`http://localhost:3001/users/${userId}`, {
method: "GET",
headers: { Authorization: `Bearer ${token}` },
});
const data = await response.json();
if(response.statuse===200){
setUser(data);
}else{console.log(response)}
};
I am also working fetch in react. Do not forget to use
try{}
catch(err){
console.log(err)}
Sometimes when I click the Add button the function is adding an empty array to the JSON file. But sometimes it works as intended. I've tried moving the variables and state around and it is still doing the same thing. The exercise prop comes from a search of an API and the prop is passed down to this component. The component displays a list of saved exercise cards that can be added to the database. Why is this happening?
import {
Button,
Card,
CardContent,
CardMedia,
Container,
Typography,
} from "#mui/material";
import { Box } from "#mui/system";
import React, { useState } from "react";
const ExerciseCard = ({ exercise }) => {
const [selectedExercise, setSelectedExercise] = useState([]);
const [selectedExerciseName, setSelectedExerciseName] = useState();
const [fetchedData, setFetchedData] = useState([]);
const addExerciseToDB = async () => {
await fetch("http://localhost:3001/savedexercises")
.then((res) => {
return res.json();
})
.then((data) => {
setFetchedData(data);
return fetchedData;
});
const savedFetchedName = fetchedData.map((fetched) => fetched.name);
setSelectedExercise([]);
setSelectedExercise({
apiId: exercise.id,
name: exercise.name,
target: exercise.target,
gifUrl: exercise.gifUrl,
});
setSelectedExerciseName(exercise.name);
if (savedFetchedName.includes(selectedExerciseName)) {
console.log("already added exercise");
} else {
console.log("adding new exercise");
await fetch("http://localhost:3001/savedExercises", {
method: "POST",
body: JSON.stringify(selectedExercise),
headers: { "Content-Type": "application/json" },
});
}
};
return (
<>
<Container maxWidth="xl">
<Box>
<Card>
<CardMedia
component="img"
alt={exercise.name}
image={exercise.gifUrl}
/>
<CardContent sx={{ pb: 2, height: "75px" }}>
<Typography variant="h5" sx={{ pb: 1 }}>
{exercise.name.toUpperCase()}
</Typography>
<Typography variant="body2">
{exercise.target.toUpperCase()}
</Typography>
</CardContent>
<Box>
<Box>
<Button
variant="contained"
color="error"
size="medium"
sx={{ m: 2 }}
onClick={() => addExerciseToDB()}
>
Add
</Button>
</Box>
</Box>
</Card>
</Box>
</Container>
</>
);
};
export default ExerciseCard;
await fetch("http://localhost:3001/savedexercises")
.then((res) => {
return res.json();
})
.then((data) => {
setFetchedData(data);
return fetchedData;
});
When I make API call and store the response in useState, it shows the data while running console.log(), however when this state value is passed as an argument to another component which is supposed to take the data and mapped it to show the result, it gives me an error saying
" Cannot read properties of undefined (reading 'map')"
Can anyone help me figure out what's wrong with my code?
Edit - As Mr.Silva suggested below, I added {menFootwears &&
menFootwears.map((menFootwear)=> () )}
It no longer shows error anymore, however, it also doesn't show the
data even though the data shows as an output in console.log() in
Product.jsx whereas it shows undefined in MenShoes.jsx and WomenShoes.jsx
Here's my code for Product.jsx
import { useMediaQuery } from '#mui/material';
import { Box } from '#mui/system';
import React from 'react'
import { theme } from '../style/theme';
import MenShoes from './collections/MenShoes';
import WomenShoes from './collections/WomenShoes';
export const Products = () => {
const matchScreen = useMediaQuery(theme.breakpoints.down('md'))
const [isLoading, setIsLoading] = React.useState(true);
const [menFootwears, setMenFootwears] = React.useState([]);
const [womenFootwears, setWomenFootwears] = React.useState([]);
//Women FootWears
async function fetchWomenFootwear () {
setIsLoading(true)
await fetch('https://dummyjson.com/products/category/womens-shoes')
.then(response => response.json())
.then(response => setWomenFootwears(response.products))
setIsLoading(false);
}
//Men Footwears
async function fetchMenFootwear () {
setIsLoading(true)
await fetch('https://dummyjson.com/products/category/mens-shoes')
.then(response => response.json())
.then(response => setMenFootwears(response.products))
setIsLoading(false)
}
React.useEffect(()=> {
fetchWomenFootwear()
fetchMenFootwear()
}, [])
const handleProductCard = (id) => {
console.log('hello')
}
console.log( womenFootwears, menFootwears)
return (
<Box>
<WomenShoes data={womenFootwears} onclick={handleProductCard} loadingStatus={isLoading}/>
<MenShoes data={menFootwears} onclick={handleProductCard} loadingStatus={isLoading}/>
</Box>
)
}
Both WomenShoes and MenShoes are designed using the same code except for the API response array data.
MenShoes/WomenShoes.jsx
import { ShoppingCartSharp } from '#mui/icons-material';
import { Button, Card, CardActionArea, CardContent, CardMedia, Divider, Rating, Skeleton, Typography, useMediaQuery } from '#mui/material';
import { Box } from '#mui/system';
import React from 'react'
import { theme } from '../../style/theme';
export default function MenShoes({menFootwears, handleProductCard, isLoading}) {
const matchScreen = useMediaQuery(theme.breakpoints.down('md'))
return(
<Box pt={2} mt={4}>
<Divider variant='middle' sx={{
"&.MuiDivider-root": {
"&::before, &::after": {
borderTopColor:theme.palette.primary.light,
borderTopWidth:'thin',
borderTopStyle:'solid'
},
}
}}>
<Typography color={theme.palette.primary.main} variant={!matchScreen ? 'h3': 'h5'}>
Men Footwears Collections
</Typography>
</Divider>
<Box display='flex'
justifyContent='space-evenly'
alignItems='center'
flexWrap='wrap'
pt={2}
mt={2}
px={2}>
{menFootwears.map((menFootwear)=> (
<Card key={menFootwear.id}
sx={{maxWidth:335,
height:'auto',
marginTop:'3.5em',
flex:!matchScreen ? '0 0 45%' : '0 0 80%'
}}
elevation={4}
onClick={()=>{handleProductCard(menFootwear.id)}}>
<CardActionArea>
{isLoading ?
<>
<Skeleton variant='rectangular' width='335' height='220' animation='wave'/>
</> :
<CardMedia component='img'
height='220'
image={menFootwear.images[0]}/>}
<CardContent sx={{
textAlign:'center',
}}>
{ isLoading ?
<>
<Skeleton variant='h6' animation='wave'/>
</> :
<Typography gutterBottom variant='h6'
fontWeight='bold'
color={theme.palette.primary.main}>
{menFootwear.title}
</Typography>}
{isLoading ?
<>
<Skeleton variant='body2' animation='wave'/>
</> :
<Typography variant='body2' gutterBottom color={theme.palette.primary.dark}>
Brand : {menFootwear.brand}
</Typography>}
{ isLoading ?
<>
<Skeleton variant='h5' animation='wave'/>
</> :
<Typography variant='h5' gutterBottom color={theme.palette.primary.main}>
$ {menFootwear.price}
</Typography>}
<Rating
size='small'
name="rating"
value={menFootwear.rating}
readOnly/>
</CardContent>
</CardActionArea>
{ isLoading ?
<>
<Skeleton variant='rectangular' width='335' height='20' animation='wave'/>
</> :
<Button size='medium'
sx={{all:'unset',
textAlign:'center',
fontFamily:theme.typography.fontFamily,
fontSize:16,
width:'100%',
padding:'0.7em',
margin:0,
color:'white',
background:`linear-gradient(90deg, ${theme.palette.primary.main},transparent) ${theme.palette.tertiary.main}`,
transition:'background 0.5s',
'&:hover': {
background:theme.palette.secondary.main,
}
}}>
<span style={{display:'inline-flex', alignItems:'center'}}>
<ShoppingCartSharp size='small'/> Add to Cart
</span>
</Button>}
</Card>
))}
</Box>
</Box>
)
}
Check before using the map if the variable menFootwears is not undefined or if the array is empty.
{menFootwears && menFootwears.map(el => () )}
I have a few pictures in my react project which I get from my JSON file,I need it to open in full screen when I click on the picture, but the pictures open all at once and not in full screen, perhaps my choice of solution is not the right one.Im new at react so any help or suggestions would help me. have this code:
import React from "react";
import axios from "axios";
import Card from "#material-ui/core/Card";
import CardActionArea from "#material-ui/core/CardActionArea";
import CardContent from "#material-ui/core/CardContent";
import CardMedia from "#material-ui/core/CardMedia";
import Typography from "#material-ui/core/Typography";
import "../App.scss";
export default class Portfolio extends React.Component {
state = {
persons: [],
};
handleShowDialog = () => {
this.setState({ isOpen: !this.state.isOpen });
console.log("cliked");
};
// onClick={() => imageClick()}
componentDidMount() {
axios.get("http://localhost:3000/persons.json").then((res) => {
const persons = res.data;
this.setState({ persons });
});
}
render() {
// const imageClick = () => {
// }
return (
<div className="container">
<div className="row justify-content-center">
{this.state.persons.map((person) => (
<Card key={person.id} className="col-3 axios-items">
<CardActionArea>
<CardMedia
component="img"
alt={person.alt}
height="140"
image={person.src}
title={person.title}
onClick={this.handleShowDialog}
/>
{this.state.isOpen && (
<dialog
className="dialog"
style={{ position: "absolute" }}
open
onClick={this.handleShowDialog}
>
<img
className="image"
src={person.src}
onClick={this.handleShowDialog}
alt="no image"
/>
</dialog>
)}
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{person.title}
</Typography>
<Typography
variant="body2"
color="textSecondary"
component="p"
>
{person.desc}
</Typography>
</CardContent>
</CardActionArea>
</Card>
))}
</div>
</div>
);
}
}
I think you can use another state too..
import React from "react";
import axios from "axios";
import Card from "#material-ui/core/Card";
import CardActionArea from "#material-ui/core/CardActionArea";
import CardContent from "#material-ui/core/CardContent";
import CardMedia from "#material-ui/core/CardMedia";
import Typography from "#material-ui/core/Typography";
import "../App.scss";
export default class Portfolio extends React.Component {
state = {
persons: [],
};
handleShowDialog = (id) => {
this.setState({ ...this.state, selected: id, isOpen: true });
console.log("cliked");
};
handleHideDialog = () => {
this.setState({ ...this.state, isOpen: false });
console.log("closed");
};
// onClick={() => imageClick()}
componentDidMount() {
axios.get("http://localhost:3000/persons.json").then((res) => {
const persons = res.data;
this.setState({ persons });
});
}
render() {
// const imageClick = () => {
// }
return (
<div className="container">
<div className="row justify-content-center">
{this.state.persons.map((person) => (
<Card key={person.id} className="col-3 axios-items">
<CardActionArea>
<CardMedia
component="img"
alt={person.alt}
height="140"
image={person.src}
title={person.title}
onClick={()=>{this.handleShowDialog(person.id)}}
/>
{(this.state.isOpen&&this.state.selected === person.id) && (
<dialog
className="dialog"
style={{ position: "absolute" }}
open
onClick={this.handleHideDialog}
>
<img
className="image"
src={person.src}
onClick={this.handleShowDialog}
alt="no image"
/>
</dialog>
)}
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{person.title}
</Typography>
<Typography
variant="body2"
color="textSecondary"
component="p"
>
{person.desc}
</Typography>
</CardContent>
</CardActionArea>
</Card>
))}
</div>
</div>
);
}
}
I am trying to Update Material UI LinearProgressWithLabel progress value with my own Value. I am getting my value from on upload progress in the Axios.post method and it is the percent value below which is a number.
<Grid item xs>
<LinearWithValueLabel value={percent}/>
</Grid>
And then the Progress Bar:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import LinearProgress, { LinearProgressProps } from '#material-ui/core/LinearProgress';
import Typography from '#material-ui/core/Typography';
import Box from '#material-ui/core/Box';
interface Props {
value: number;
}
const LinearProgressWithLabel: React.FC<Props> = ({ value }) => {
return (
<Box display="flex" alignItems="center">
<Box width="100%" mr={1}>
<LinearProgress variant="determinate" />
</Box>
<Box minWidth={35}>
<Typography variant="body2" color="textSecondary">{`${Math.round(
value,
)}%`}</Typography>
</Box>
</Box>
);
}
const useStyles = makeStyles({
root: {
width: '100%',
},
});
const LinearWithValueLabel: React.FC = () => {
const classes = useStyles();
const [progress, setProgress] = React.useState(0);
React.useEffect(() => {
const timer = setInterval(() => {
setProgress((prevProgress) => (prevProgress >= 100 ? 0 : progress));
}, 800);
return () => {
clearInterval(timer);
};
}, []);
return (
<div className={classes.root}>
<LinearProgressWithLabel value={progress} />
</div>
);
}
export default LinearWithValueLabel;
But I am getting this error in the console:
Warning: Material-UI: you need to provide a value prop when using the determinate or buffer variant of LinearProgress
What am I doing wrong?
You are missing the value prop.
const LinearProgressWithLabel: React.FC<Props> = ({ value }) => {
return (
<Box display="flex" alignItems="center">
<Box width="100%" mr={1}>
<LinearProgress variant="determinate" value={value} />
</Box>
<Box minWidth={35}>
<Typography variant="body2" color="textSecondary">{`${Math.round(
value,
)}%`}</Typography>
</Box>
</Box>
);
}