Data driven Tabs with Material UI React - reactjs

I want to render Tabs & Tabpanels with the data array which I got.
I have rendered the Tab headings but I couldn't render the Tabpanel data when the Tabs are clicked. Following is my code.
I want to show the theaters for each date if the date Tab is selected.
I have tried many but failed. Appreciate your suggestions.
Thanks...
import React from "react";
import PropTypes from "prop-types";
import { makeStyles } from "#material-ui/core/styles";
import AppBar from "#material-ui/core/AppBar";
import Tabs from "#material-ui/core/Tabs";
import Tab from "#material-ui/core/Tab";
import PhoneIcon from "#material-ui/icons/Phone";
import FavoriteIcon from "#material-ui/icons/Favorite";
import PersonPinIcon from "#material-ui/icons/PersonPin";
import HelpIcon from "#material-ui/icons/Help";
import ShoppingBasket from "#material-ui/icons/ShoppingBasket";
import ThumbDown from "#material-ui/icons/ThumbDown";
import ThumbUp from "#material-ui/icons/ThumbUp";
import Typography from "#material-ui/core/Typography";
import Box from "#material-ui/core/Box";
import { DateRangeSharp } from "#material-ui/icons";
const DATES = [
{
id: 1,
day: "WED",
date: 19,
theater: [{ tname: "vista" }, { tname: "liberty" }],
},
{
id: 2,
day: "THU",
date: 20,
theater: [{ tname: "PVR" }, { tname: "CCC" }],
},
{
id: 3,
day: "FRI",
date: 21,
theater: [{ tname: "vista" }, { tname: "liberty" }],
},
{ id: 4, day: "SAT", date: 22 },
{ id: 5, day: "SUN", date: 23 },
{ id: 6, day: "MON", date: 24 },
{ id: 7, day: "TUE", date: 25 },
{ id: 8, day: "WED", date: 26 },
];
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`scrollable-force-tabpanel-${index}`}
aria-labelledby={`scrollable-force-tab-${index}`}
{...other}
>
{value === index && (
<Box p={3}>
<Typography>{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.any.isRequired,
value: PropTypes.any.isRequired,
};
function a11yProps(index) {
return {
id: `scrollable-force-tab-${index}`,
"aria-controls": `scrollable-force-tabpanel-${index}`,
};
}
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
width: "100%",
backgroundColor: theme.palette.background.paper,
},
}));
export default function ScrollableTabsButtonForce() {
const classes = useStyles();
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<div className={classes.root}>
<AppBar
position="static"
style={{ background: "#333545", minHeight: 60 }}
>
<Tabs
value={value}
onChange={handleChange}
variant="scrollable"
scrollButtons="on"
indicatorColor="secondary"
textColor="primary"
aria-label="scrollable force tabs example"
style={{ minHeight: 60 }}
wrapped
>
{DATES.map((showtdates) => {
return (
<Tab
label={showtdates.date + " " + showtdates.day}
{...a11yProps(0)}
style={{ color: "#fff", fontSize: 20, minHeight: 60 }}
/>
);
})}
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
showtdates.theater
</TabPanel>
</div>
);
}

For each day in your DATES array you have to create a TabPanel and pass the index and value as prop. You can easily do this by mapping over your DATES array. Inside your map function, you can access all properties and display the theaters.
As an example, I used the List component of material-ui to list the theaters.
This could then look like this:
import React from "react";
import PropTypes from "prop-types";
import { makeStyles } from "#material-ui/core/styles";
import AppBar from "#material-ui/core/AppBar";
import Tabs from "#material-ui/core/Tabs";
import Tab from "#material-ui/core/Tab";
import PhoneIcon from "#material-ui/icons/Phone";
import FavoriteIcon from "#material-ui/icons/Favorite";
import PersonPinIcon from "#material-ui/icons/PersonPin";
import HelpIcon from "#material-ui/icons/Help";
import ShoppingBasket from "#material-ui/icons/ShoppingBasket";
import ThumbDown from "#material-ui/icons/ThumbDown";
import ThumbUp from "#material-ui/icons/ThumbUp";
import Typography from "#material-ui/core/Typography";
import Box from "#material-ui/core/Box";
import { DateRangeSharp } from "#material-ui/icons";
import { List, ListItem, ListItemText } from "#material-ui/core";
const DATES = [
{
id: 1,
day: "WED",
date: 19,
theater: [{ tname: "vista" }, { tname: "liberty" }]
},
{
id: 2,
day: "THU",
date: 20,
theater: [{ tname: "PVR" }, { tname: "CCC" }]
},
{
id: 3,
day: "FRI",
date: 21,
theater: [{ tname: "vista" }, { tname: "liberty" }]
},
{ id: 4, day: "SAT", date: 22 },
{ id: 5, day: "SUN", date: 23 },
{ id: 6, day: "MON", date: 24 },
{ id: 7, day: "TUE", date: 25 },
{ id: 8, day: "WED", date: 26 }
];
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`scrollable-force-tabpanel-${index}`}
aria-labelledby={`scrollable-force-tab-${index}`}
{...other}
>
{value === index && (
<Box p={3}>
<Typography>{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.any.isRequired,
value: PropTypes.any.isRequired
};
function a11yProps(index) {
return {
id: `scrollable-force-tab-${index}`,
"aria-controls": `scrollable-force-tabpanel-${index}`
};
}
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
width: "100%",
backgroundColor: theme.palette.background.paper
}
}));
export default function App() {
const classes = useStyles();
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<div className={classes.root}>
<AppBar
position="static"
style={{ background: "#333545", minHeight: 60 }}
>
<Tabs
value={value}
onChange={handleChange}
variant="scrollable"
scrollButtons="on"
indicatorColor="secondary"
textColor="primary"
aria-label="scrollable force tabs example"
style={{ minHeight: 60 }}
wrapped
>
{DATES.map((showtdates) => {
return (
<Tab
label={showtdates.date + " " + showtdates.day}
{...a11yProps(0)}
style={{ color: "#fff", fontSize: 20, minHeight: 60 }}
/>
);
})}
</Tabs>
</AppBar>
{/* map over dates and create TabPanel */}
{DATES.map((date, idx) => {
// check if theater property exists and create a list of theaters as an example
const theaters = date.hasOwnProperty('theater')
? date.theater.map((theater) => (
<ListItem>
<ListItemText primary="Theater name" secondary={theater.tname} />
</ListItem>
))
: null;
return (
<TabPanel value={value} index={idx}>
<List>{theaters}</List>
</TabPanel>
);
})}
</div>
);
}
Live demo:

Related

MuiTabPanl-Root Padding remove using CSS or Mui Styles?

I want to override the MUI Tab Panel Padding. I override the .MuiTabPanel-Root Class globally and inline style. But, the Tab Panel is not override. Screenshot and Code Below attached.
I want to remove the padding from the MuiTabPanel-Root class padding.
When I applied the padding as 0px in "MuiTabPanel-Root" class is not working.
But, When I remove the padding from this class .css-13xfq8m-MuiTabPanel-root Tab panel padding was removed. I don't know how to override the "TabPanel-root padding" using react js
CSS Global :
.MuiTabPanel-root{
padding: 0px;
}
CSS Inline :
<TabPanel value="1" classes={{
"& .MuiTabPanel-root": {
padding: "0px",
},
}}>
Full Code Tab Component :
import * as React from 'react';
import Box from '#mui/material/Box';
import Tab from '#mui/material/Tab';
import TabContext from '#mui/lab/TabContext';
import TabList from '#mui/lab/TabList';
import TabPanel from '#mui/lab/TabPanel';
import HistoryTable from '../HistoryTable/HistoryTable';
import { Button } from '#mui/material';
import SampleTable from './SampleTable';
import './TradeTab.css';
import { MuiThemeProvider, createTheme } from "#material-ui/core/styles";
import { orange, pink, green } from "#material-ui/core/colors";
export default function SampleTabControl() {
const theme = createTheme({
overrides: {
MuiTabs: {
indicator: {
backgroundColor: 'red'
}
},
MuiTab: {
root: {
"&:hover": {
backgroundColor: pink[100],
color: pink[700]
},
".MuiTabPanel-root":{
padding:0
}
},
selected: {
backgroundColor: orange[100],
color: orange[700],
"&:hover": {
backgroundColor: 'green',
color: green[700]
}
}
}
}
});
const [value, setValue] = React.useState('1');
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<MuiThemeProvider theme={theme}>
<Box sx={{ width: '100%', typography: 'body1'}}>
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<TabList onChange={handleChange} aria-label="lab API tabs example">
<Tab label="Item One" value="1" style={{color: "white", fontWeight:"500"}}
sx={{backgroundColor: value=="1" ? "blue" : "lightgrey" }}/>
<Tab label="Item Two" value="2" style={{color: "white", fontWeight:"500", marginLeft:'10px'}}
sx={{backgroundColor: value=="2" ? "blue" : "lightgrey"}}/>
<Button variant='outlined' style={{marginLeft:'100px', size:'small', height:'30px', marginTop:"10px"}}>1X</Button>
</TabList>
</Box>
<TabPanel value="1" classes={{
"& .MuiTabPanel-root": {
padding: "0px",
},
}}>
<SampleTable/>
</TabPanel>
<TabPanel value="2">Item Two</TabPanel>
<TabPanel value="3">Item Three</TabPanel>
</TabContext>
</Box>
</MuiThemeProvider>
);
}
Full Code Table :
import React, { useMemo } from 'react';
import MaterialReactTable from 'material-react-table';
import { makeStyles } from '#mui/styles';
//nested data is ok, see accessorKeys in ColumnDef below
const data = [
{
name: {
firstName: 'John',
lastName: 'Doe',
},
address: '261 Erdman Ford',
city: 'East Daphne',
state: 'Kentucky',
},
{
name: {
firstName: 'Jane',
lastName: 'Doe',
},
address: '769 Dominic Grove',
city: 'Columbus',
state: 'Ohio',
},
{
name: {
firstName: 'Joe',
lastName: 'Doe',
},
address: '566 Brakus Inlet',
city: 'South Linda',
state: 'West Virginia',
},
{
name: {
firstName: 'Kevin',
lastName: 'Vandy',
},
address: '722 Emie Stream',
city: 'Lincoln',
state: 'Nebraska',
},
{
name: {
firstName: 'Joshua',
lastName: 'Rolluffs',
},
address: '32188 Larkin Turnpike',
city: 'Charleston',
state: 'South Carolina',
},
];
const SampleTable = () => {
//should be memoized or stable
const columns = useMemo(
() => [
{
accessorKey: 'name.firstName', //access nested data with dot notation
header: 'First Name',
},
{
accessorKey: 'name.lastName',
header: 'Last Name',
},
{
accessorKey: 'address', //normal accessorKey
header: 'Address',
},
{
accessorKey: 'city',
header: 'City',
},
{
accessorKey: 'state',
header: 'State',
},
],
[],
);
return <MaterialReactTable columns={columns} data={data} style={{padding:'0px'}}/>;
};
export default SampleTable;
I try to remove the padding for "MuiTabPanel-root".
Expected Result :
Remove the padding from "MuiTabPanel-Root"

TypeError: venuesDates.map is not a function React

I'm trying to render the Tab element from Material UI. It works the first time but if I go back to another screen and comes back it gives me the following error. It gives me headaches now I'm very new to React.
TypeError: venuesDates.map is not a function
following is my code
import React, { useEffect, useState }from "react";
import PropTypes from "prop-types";
import { makeStyles } from "#material-ui/core/styles";
import AppBar from "#material-ui/core/AppBar";
import Tabs from "#material-ui/core/Tabs";
import Tab from "#material-ui/core/Tab";
import PhoneIcon from "#material-ui/icons/Phone";
import FavoriteIcon from "#material-ui/icons/Favorite";
import PersonPinIcon from "#material-ui/icons/PersonPin";
import HelpIcon from "#material-ui/icons/Help";
import ShoppingBasket from "#material-ui/icons/ShoppingBasket";
import ThumbDown from "#material-ui/icons/ThumbDown";
import ThumbUp from "#material-ui/icons/ThumbUp";
import Typography from "#material-ui/core/Typography";
import Box from "#material-ui/core/Box";
import { DateRangeSharp } from "#material-ui/icons";
import { List, ListItem, ListItemText } from "#material-ui/core";
const DATES = [
{
id: 1,
day: "WED",
date: 19,
theater: [{ tname: "vista", price: 450 }, { tname: "liberty", price: 550 }]
},
{
id: 2,
day: "THU",
date: 20,
theater: [{ tname: "PVR" }, { tname: "CCC" }]
},
{
id: 3,
day: "FRI",
date: 21,
theater: [{ tname: "vista" }, { tname: "liberty" }]
},
{ id: 4, day: "SAT", date: 22 },
{ id: 5, day: "SUN", date: 23 },
{ id: 6, day: "MON", date: 24, theater: [{ tname: "vista" }, { tname: "liberty" }] },
{ id: 7, day: "TUE", date: 25 },
{ id: 8, day: "WED", date: 26 }
];
const showDatesNtimes = []
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`scrollable-force-tabpanel-${index}`}
aria-labelledby={`scrollable-force-tab-${index}`}
{...other}
>
{value === index && (
<Box p={3}>
<Typography>{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.any.isRequired,
value: PropTypes.any.isRequired
};
function a11yProps(index) {
return {
id: `scrollable-force-tab-${index}`,
"aria-controls": `scrollable-force-tabpanel-${index}`
};
}
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
width: "100%",
backgroundColor: theme.palette.background.paper
}
}));
export default function ScrollableTabsButtonForce() {
const classes = useStyles();
const [value, setValue ] = React.useState(0);
const [venuesDates, setvenuesDates] = React.useState(0);
useEffect(() => {
const url = "http://sandbox-api.tickets.lk/v1/movie/3232/showtime";
const requestOptions = (token) => {
return ({
method: 'GET',
headers: { 'Content-Type': 'application/json', 'client_token': 'ebd86470-7e90-4ece-9e89-1b6d4d2cbb61' }
})
};
const fetchData = async () => {
try {
const response = await fetch(url, requestOptions());
const json = await response.json();
// console.log(json);
// console.log(json.data.venueDateShowtime)
setvenuesDates(json.data.venueDateShowtime);
}
catch (error) {
console.log("error",error);
}
};
fetchData();
})
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<div className={classes.root}>
<AppBar
position="static"
style={{ background: "#333545", minHeight: 60 }}
>
<Tabs
value={value}
onChange={handleChange}
variant="scrollable"
scrollButtons="on"
indicatorColor="secondary"
textColor="primary"
aria-label="scrollable force tabs example"
style={{ minHeight: 60 }}
wrapped
>
{venuesDates.map((showtdates) => {
return (
<Tab
label={showtdates.date}
{...a11yProps(0)}
style={{ color: "#fff", fontSize: 20, minHeight: 60 }}
/>
);
})}
</Tabs>
</AppBar>
{/* map over dates and create TabPanel */}
{/* // check if theater property exists and create a list of theaters as an example */}
{venuesDates.map((date, idx) => {
const venues = date.hasOwnProperty("venues")
? date.venues.map((venues) => (
<ListItem>
<ListItemText
primary={venues.venue}
secondary={venues.venueId}
/>
</ListItem>
))
: null;
return (
<TabPanel value={value} index={idx}>
<List>{venues}</List>
</TabPanel>
);
})}
</div>
);
}
Hoping for any suggestions... 🙏🙏🙏🙏
Since you are using venuesDates as an array, it's important you initialize it as an array.
Try this
const [venuesDates, setvenuesDates] = React.useState([]);

Material Table rowStyle background color change based on cell value in

I am trying to have the color of the row change colors based on the priority number. For example, if the priority is 4 the color of the entire row should be blue. The problem is that I'm unsure of how to achieve this. I know Material Table assigns ID's to the rows, but I have no way of accessing them. Below is what I have come up with so far. I need options[backgroundColor] to be set based on the priority number. I have a codesandbox here as well https://codesandbox.io/s/notifications-material-ui-spq45
import React from "react";
import { Container } from "react-bootstrap";
import MaterialTable from "material-table";
import FilterListIcon from "#material-ui/icons/FilterList";
import SearchIcon from "#material-ui/icons/Search";
import FirstPage from "#material-ui/icons/FirstPage";
import LastPage from "#material-ui/icons/LastPage";
import ChevronLeft from "#material-ui/icons/ChevronLeft";
import ChevronRight from "#material-ui/icons/ChevronRight";
import CloseIcon from "#material-ui/icons/Close";
function App() {
//loop through the array of priority numbers, and display color based on number
function colors(num) {
for(let i = 0; i < num.length; i++) {
if (num[i] === 4) {
options.rowStyle.backgroundColor = "blue";
}
if (num[i] === 3) {
options.rowStyle.backgroundColor = "red";
}
console.log(num[i]);
}
}
let data = [
{
date: "06-29-2021",
subject: "CANBUS LOSS, Automatic Reboot!",
message:
"SCMs CANBUS LOSS for more than 15 min, Automatic System Reboot!",
category: "System",
priority: 4,
error: "SYS0080"
},
{
date: "06-28-2021",
subject: "Reboot!",
message: "Automatic System Reboot!",
category: "Alarm",
priority: 3,
error: "SYS0090"
},
{
date: "06-25-2021",
subject: "Testing!",
message: "Generator not running!",
category: "Generator",
priority: 2,
error: "SYS0050"
}
];
let columns = [
{ title: "Date", field: "date" },
{ title: "Subject", field: "subject" },
{ title: "Message", field: "message" },
{ title: "Category", field: "category" },
{ title: "Priority Level", field: "priority" },
{ title: "Error Code", field: "error" }
];
let options = {
filtering: false,
sorting: true,
rowStyle: {
fontFamily: "Mulish-Regular",
backgroundColor: ""
},
headerStyle: {
fontFamily: "Mulish-Regular",
fontSize: "1.1em",
fontWeight: "600",
backgroundColor: "#D1D1D8"
},
searchFieldStyle: {
fontFamily: "Mulish-Regular"
}
};
// Loop through all the data and find the priority number, and put it in an array
let map = data.map((x) => x.priority);
console.log(map);
colors(map);
return (
<>
<Container>
<MaterialTable
title=""
columns={columns}
data={data}
options={options}
icons={{
Filter: (props) => <FilterListIcon style={{ fill: "#2D3155 " }} />,
Search: (props) => <SearchIcon style={{ fill: "#2D3155 " }} />,
FirstPage: (props) => <FirstPage style={{ fill: "#2D3155 " }} />,
LastPage: (props) => <LastPage style={{ fill: "#2D3155 " }} />,
NextPage: (props) => <ChevronRight style={{ fill: "#2D3155 " }} />,
PreviousPage: (props) => (
<ChevronLeft style={{ fill: "#2D3155 " }} />
),
SortArrow: (props) => (
<FilterListIcon
style={{ fill: "#2D3155 ", fontSize: "1.4em", margin: ".4em" }}
/>
),
ResetSearch: (props) => <CloseIcon style={{ fill: "#2D3155 " }} />
}}
/>
</Container>
</>
);
}
export default App;
As you can read in the docs, rowStyle accepts an object or a function.
Hence, you can set rowStyle using a function that receives rowData as parameter, an example:
const rowBackgroundColors = {
"2": "yellow", // just for example, remove it if you don't need
"3": "orange",
"4": "red",
};
const options = {
// ...
rowStyle: (rowData) => {
return {
fontFamily: "Mulish-Regular",
backgroundColor: rowBackgroundColors[rowData.priority] ?? "#fff",
};
},
// ...
};

how to increment value by +1 by clicking button in react js

am stuck with a problem when I click on like button I want it increment by +1, can anyone tell me how can I do it, I try it but I can't solve it.
below I share my all code that I used to make my small application. if you have question free feel to ask me.
Music.js
This is my music form where I wrote my whole code.
import React, { useState, useRef, useEffect } from 'react';
import { makeStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
import ExitToAppIcon from '#material-ui/icons/ExitToApp';
import RadioIcon from '#material-ui/icons/Radio';
import firebase from '../Firebase';
import SearchBar from "material-ui-search-bar";
import { useHistory } from 'react-router-dom';
import { Container, Input, TextField } from '#material-ui/core';
import './Music.css';
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableContainer from '#material-ui/core/TableContainer';
import TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import Paper from '#material-ui/core/Paper';
import ThumbUpAltIcon from '#material-ui/icons/ThumbUpAlt';
// import { useSelector } from 'react-redux';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
search: {
marginTop: 30,
},
table: {
minWidth: 650,
marginBottom: 10,
},
cells: {
marginTop: 50,
},
thumb: {
color: '#e75480',
},
name: {
color: 'blue',
padding: 10,
fontSize: 20,
},
audios: {
display: 'flex',
margin: 'auto',
height: 50,
width: 500,
alignItems: 'center'
},
icon: {
fontSize: 40,
color: '#e75480',
cursor:'pointer'
}
}));
const Music = () => {
const history = useHistory();
const inputRef = useRef(null);
const [search, setSearch] = useState("");
const [like, setLike] = useState(false);
const [music,setMusics] = useState([
{
id:"1",
name:"Arijit singh",
audiosrc:"https://upload.wikimedia.org/wikipedia/commons/1/15/Bicycle-bell.wav",
},
{
id:"2",
name:"Atif Aslam",
audiosrc:"https://upload.wikimedia.org/wikipedia/commons/1/15/Bicycle-bell.wav",
},
{
id:"3",
name:"Sonu Nigam",
audiosrc:"https://upload.wikimedia.org/wikipedia/commons/1/15/Bicycle-bell.wav",
},
{
id:"4",
name:"Neha kakkar",
audiosrc:"https://upload.wikimedia.org/wikipedia/commons/1/15/Bicycle-bell.wav",
},
])
const likeButton = (id)=>{
const likebuttons = music.find((curElem)=>{
return curElem.id == id
})
setLike({likebuttons:like+1})
console.log(likebuttons);
}
console.log(search);
// Logout Functionality
const Logout = () => {
firebase.auth().signOut().then(() => {
alert("Logout Successfull...");
history.push('/');
}).catch((error) => {
console.log(error);
});
}
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static" style={{ width: '100%' }}>
<Toolbar>
<IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
<RadioIcon style={{ fontSize: "30px" }} /> React Music
</IconButton>
<Typography variant="h6" className={classes.title}>
</Typography>
<Button color="inherit" onClick={Logout}> <ExitToAppIcon /> Logout </Button>
</Toolbar>
</AppBar>
<Container>
<SearchBar className={classes.search}
value={search}
onChange={(newValue) => setSearch(newValue)}
/>
<Table className={classes.table} aria-label="simple table">
<TableBody>
{music && music.map(mus=>{
return(
<TableRow>
<TableCell style={{ display: 'flex', justifyContent: 'space-around' }}>
<div>
<h3>{like} <ThumbUpAltIcon className={classes.icon} onClick={()=>likeButton(music.id)} /> {mus.name}</h3>
</div>
<div>
<audio ref={inputRef} src={mus.audiosrc} className={classes.audios} controls />
</div>
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</Container>
</div>
);
}
export default Music;
Make following changes in your code:
const [like, setLike] = useState(false);
to
const [like, setLike] = useState(0);
and
setLike({likebuttons:like+1})
to
setLike(like+1);
and try again.
If you want to have like count for all music data,
First you should change like state to store object
const [like, setLike] = useState({});
Change your like button function to store data in object
const likeButton = (musicId)=>{
setLike({...like, like[musicId]: like[musicId] + 1 || 1 })
}
Now change how you are showing like count as below:
<div>
<h3>{like[music.id]} <ThumbUpAltIcon className={classes.icon} onClick={()=>likeButton(music.id)} /> {mus.name}</h3>
</div>
first, you should change your states.
each music has it's own like number, so you can't use 1 like state for all.
each item in your music array should have a value to store it's own like
numbers.
something like :
const [music,setMusics] = useState([
{
id:"1",
name:"Arijit singh",
audiosrc:"https://uploa...",
likeNumbers:0,
},
...
]
then your onClick should iterate the music array, find the clicked item and change it's likeNumbers value.
something like this:
cosnt handleClick = (id) => {
setMusic((prevState) => prevState.map((item) => {
if (item.id === id ) {
return {...item, likeNumbers:likeNumbers + 1 }
} else {
return item
}
})
}
to be clear:
first you should take the last version of your state, then in the process of iterating, find the clicked item and update it. to avoid mutate your state ( because items are objects ), you should make a copy first, then changed it. I mean here:
return {...item, likeNumbers:likeNumbers + 1 }
after all a part of your jsx code should be changed to :
<h3>{mus.likeNumber} <ThumbUpAltIcon className={classes.icon} onClick={()=>likeButton(music.id)} /> {mus.name}</h3>
First you need to make type as number instead of boolean
const [like, setLike] = useState(0);
and then
const likeButton = (id)=>{
const likebuttons = music.find((curElem)=>{
return curElem.id == id
})
setLike(likebuttons+1);
console.log(likebuttons);
}
Or
you can add no. of likes in same array object and just update that like field
You can check below example created for you. I hope it will help you.
It's having only like functionality
import "./styles.css";
import React, { useState } from "react";
export default function App() {
const [likedSong, setLikedSong] = useState({
likes: 0,
id: 0
});
const [music, setMusics] = useState([
{
id: "1",
name: "Arijit singh",
audiosrc:
"https://upload.wikimedia.org/wikipedia/commons/1/15/Bicycle-bell.wav",
likes: 0
},
{
id: "2",
name: "Atif Aslam",
audiosrc:
"https://upload.wikimedia.org/wikipedia/commons/1/15/Bicycle-bell.wav",
likes: 0
},
{
id: "3",
name: "Sonu Nigam",
audiosrc:
"https://upload.wikimedia.org/wikipedia/commons/1/15/Bicycle-bell.wav",
likes: 0
},
{
id: "4",
name: "Neha kakkar",
audiosrc:
"https://upload.wikimedia.org/wikipedia/commons/1/15/Bicycle-bell.wav",
likes: 0
}
]);
const handleLike = (list) => {
if (likedSong.id === list.id) {
setLikedSong({ ...likedSong, id: list.id, likes: ++likedSong.likes });
} else {
setLikedSong({ ...likedSong, id: list.id, likes: 0 });
}
};
return (
<div className="App">
{music.map((mus) => (
<div key={mus.id} className="music-list">
<div>
{mus.id === likedSong.id && (
<span className="no-likes">{likedSong.likes}</span>
)}
<span className="btn-like" onClick={() => handleLike(mus)}>
Like
</span>
{mus.name}
</div>
</div>
))}
</div>
);
}
Live working demo

ReactJs adding active class to DIV

I have 3 DIVs, dynamically created. My target is: when any div is clicked to add active class to it, and of course if any other has that active class to remove it. How can I achieve that?
import React, { useState } from "react";
import "./styles/App.css";
import { Container, Box, Typography, makeStyles } from "#material-ui/core";
const useStyles = makeStyles({
mainBox: {
display: "flex",
justifyContent: "space-evenly"
},
mybox: {
backgroundColor: "#9fa8da",
padding: "40px",
color: "#fff",
maxWidth: 300
}
});
function App() {
const clasess = useStyles();
const [active, setactive] = useState("");
const mydata = [
{
id: 1,
name: "Ganesh",
des: "UI Developer"
},
{
id: 2,
name: "Suresh",
des: "Accountant"
},
{
id: 3,
name: "Srikanth",
des: "Digital"
}
];
const onClick = index => {
setactive("active");
};
return (
<Container>
<Box className={clasess.mainBox}>
{mydata.map((val, index) => {
return (
<>
<Box
boxShadow={1}
key={index}
onClick={e => {
onClick(index);
}}
className={active}
>
<Typography variant="h4">{val.name}</Typography>
<Typography>{val.des}</Typography>
</Box>
</>
);
})}
</Box>
</Container>
);
}
export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
I have 3 DIVs, dynamically created. My target is: when any div is clicked to add active class to it, and of course if any other has that active class to remove it. How can I achieve that?
I have 3 DIVs, dynamically created. My target is: when any div is clicked to add active class to it, and of course if any other has that active class to remove it. How can I achieve that?
Try to check when active id is the clicked id:
import React, { useState } from "react";
import "./styles/App.css";
import { Container, Box, Typography, makeStyles } from "#material-ui/core";
const useStyles = makeStyles({
mainBox: {
display: "flex",
justifyContent: "space-evenly"
},
mybox: {
backgroundColor: "#9fa8da",
padding: "40px",
color: "#fff",
maxWidth: 300
}
});
function App() {
const clasess = useStyles();
const [active, setActive] = useState();
const mydata = [
{
id: 1,
name: "Ganesh",
des: "UI Developer"
},
{
id: 2,
name: "Suresh",
des: "Accountant"
},
{
id: 3,
name: "Srikanth",
des: "Digital"
}
];
const onClick = id => {
setActive(id);
};
return (
<Container>
<Box className={clasess.mainBox}>
{mydata.map((val, index) => {
return (
<>
<Box
boxShadow={1}
key={index}
onClick={e => {
onClick(val.id);
}}
className={val.id == id ? active : deactive}
>
<Typography variant="h4">{val.name}</Typography>
<Typography>{val.des}</Typography>
</Box>
</>
);
})}
</Box>
</Container>
);
}
export default App;
You already managed on your Box component to add an "active" classname when one of them is Clicked.
But, you need to add some style or something to show for those "active" elements.
Inside of useStyle add the class active and test it out with some styling:
i.e)
const useStyles = makeStyles({
mainBox: {
display: "flex",
justifyContent: "space-evenly"
},
mybox: {
backgroundColor: "#9fa8da",
padding: "40px",
color: "#fff",
maxWidth: 300
},
active {
backgroundColor: "red"
}
});
I'm not sure if you need to add "active" class using classes, something like :
<Box
boxShadow={1}
key={index}
onClick={e => {
onClick(index);
}}
className={classes.active}
>
<Typography variant="h4">{val.name}</Typography>
<Typography>{val.des}</Typography>
</Box>

Resources