useStateの無限ループのエラー解消法について
useStateの無限ループのエラー解消法について
Next.jsでMaterial-uiのCardコンポーネントを使用しmapで複数のカードを作る際にエラーが発生しました。
解決方法を教えてください。
発生している問題・エラー
mapで複数のアコーディオンボタンを作成した際に、useStateで無限エラーが発生します。
下記は一部のソースコードを抜粋したものです。
useStateでfalseを格納し、ボタンをクリックした際に反転するように記載しています。
その際に下記のエラーの対処方法がわかりません。
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
index.jsx
export function ProfileCard() {
const [expanded, setExpanded] = useState(false);
const plusButton = useCallback(() => {
setExpanded(() => !expanded);
}, []);
components/CardItem.jsx
<CardActions disableSpacing>
<IconButton
onClick={plusButton}
className={clsx(classes.expand, expanded && classes.expandOpen)}
aria-label="plus"
aria-expanded={expanded}
>
<ExpandMoreIcon />
</IconButton>
</CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<CardContent>
...
</CardContent>
</Collapse>
該当するソースコード
index.jsx
import { useCallback, useState } from "react";
import { CardItem } from "./CardItem";
import { Grid } from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
root: {
margin: "16px",
maxWidth: 445,
},
media: {
height: 0,
paddingTop: "50%",
},
expand: {
transform: "rotate(0deg)",
marginLeft: "auto",
transition: theme.transitions.create("transform", {
duration: theme.transitions.duration.leavingScreen,
}),
},
expandOpen: {
transform: "rotate(180deg)",
},
}));
export function ProfileCard() {
const classes = useStyles();
const [expanded, setExpanded] = useState(false);
const photos = ["kyoto.jpg", "nagasaki.jpg", "niigata.jpg"];
const plusButton = useCallback(() => {
setExpanded(() => !expanded);
}, []);
return (
<>
<Grid container>
{photos.map((photo) => {
return (
<Grid item xs key={photo}>
<CardItem
classes={classes}
plusButton={plusButton()}
expanded={expanded}
photo={photo}
/>
</Grid>
);
})}
</Grid>
</>
);
}
components/CardItem.jsx
import clsx from "clsx";
import {
Card,
CardHeader,
CardMedia,
CardContent,
CardActions,
Collapse,
Avatar,
IconButton,
Typography,
} from "@material-ui/core";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
export function CardItem({classes,plusButton,expanded,photo}){
return (
<Card className={classes.root}>
<CardHeader
className={classes.avatar}
title="タイトル"
subheader="サブタイトル"
/>
<CardMedia className={classes.media} image={photo} />
<CardContent>
<Typography
variant="inherit"
color="textSecondary"
display="inline"
component="p"
>
Kiyomizu
</Typography>
</CardContent>
<CardActions disableSpacing>
<IconButton
onClick={plusButton}
className={clsx(classes.expand, expanded && classes.expandOpen)}
aria-label="plus"
aria-expanded={expanded}
>
<ExpandMoreIcon />
</IconButton>
</CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<CardContent>
<Typography paragraph variant="h6" align="center">
content
</Typography>
<Typography color="textSecondary">
Kiyomizu
</Typography>
</CardContent>
</Collapse>
</Card>
);
}
自分で試したこと
下記のサイトを参考にしました。
https://qiita.com/katsuomi/items/5a062dc1e4d0ab64ae21
0