我发现唯一奇怪的是您将 useStyles 挂钩 inside 您的组件,因此每个渲染周期都会创建新样式.将它们移到组件之外。
例子:
App.js
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1
},
paper: {
padding: theme.spacing(0),
textAlign: "center",
color: theme.palette.text.primary,
backgroundColor: theme.palette.background
}
}));
function App() {
const classes = useStyles();
const { state, dispatch } = React.useContext(MainContext);
const handleClick = useCallback(
(areaName, monsterName, newCount) => {
newCount = newCount > 10 ? 10 : newCount;
newCount = newCount < 0 ? 0 : newCount;
dispatch({
type: "UPDATE_COUNT",
area: areaName,
monster: monsterName,
count: newCount
});
},
[dispatch]
);
const areaObjects = Object.entries(state).map(([area, monster]) => {
const monsters = Object.entries(monster).map(([monsterName, count]) => (
<Grid item xs={12} key={monsterName}>
<Monster
area={area}
name={monsterName}
count={count}
handleClick={handleClick}
/>
</Grid>
));
return (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2} key={area}>
<Paper className={classes.paper}>
<Grid item xs={12}>
<h3>{area}</h3>
</Grid>
{monsters}
</Paper>
</Grid>
);
});
return (
<div className={classes.root} id={"app-container"} key={"app-container"}>
<Grid container spacing={0}>
{areaObjects}
</Grid>
</div>
);
}
Monster.js
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1
},
addButtonContainer: {
backgroundColor: "lightblue"
},
subtractButtonContainer: {
backgroundColor: "lightyellow"
},
maxButtonContainer: {
backgroundColor: "lightgreen"
},
monsterName: {
textAlign: "center"
},
row: {
backgroundColor: "lightgray"
},
rowSuccess: {
backgroundColor: "lightgreen"
}
}));
export default function Monster({ area, name, count, handleClick }) {
const handleIncrement = (areaName, monsterName) => {
handleClick(areaName, monsterName, count + 1);
};
const handleDecrement = (areaName, monsterName) => {
handleClick(areaName, monsterName, count - 1);
};
const handleMaxout = (areaName, monsterName) => {
handleClick(areaName, monsterName, 10);
};
const classes = useStyles();
const rowClass = count === 10 ? classes.rowSuccess : classes.row;
return (
<Grid container item className={rowClass}>
<Grid item xs={7} className={classes.monsterName}>
{name}
</Grid>
<Grid item xs={1} className={classes.maxButtonContainer}>
<IconButton
color={"primary"}
variant={"contained"}
size={"small"}
onClick={() => handleMaxout(area, name)}
>
<ArrowUpward fontSize={"small"} />
</IconButton>
</Grid>
<Grid item xs={1} className={classes.addButtonContainer}>
<IconButton
color={"primary"}
variant={"contained"}
size={"small"}
onClick={() => handleIncrement(area, name)}
>
<Add fontSize={"small"} />
</IconButton>
</Grid>
<Grid item xs={2}>
{count}
</Grid>
<Grid item xs={1} className={classes.subtractButtonContainer}>
<IconButton
color={"secondary"}
variant={"contained"}
size={"small"}
onClick={() => handleDecrement(area, name)}
>
<Remove fontSize={"small"} />
</IconButton>
</Grid>
</Grid>
);
}
我还记住了上下文提供的state,尽管我不完全认为这部分是必要的。
index.js
import React, { useMemo } from "react";
import initialState from "./initialState";
import reducer from "./reducer";
const MainContext = React.createContext();
function MainContextProvider(props) {
const [state, dispatch] = React.useReducer(reducer, initialState);
const value = useMemo(() => ({ state, dispatch }), [state]);
return (
<MainContext.Provider value={value}>{props.children}</MainContext.Provider>
);
}
const MainContextConsumer = MainContext.Consumer;
export { MainContext, MainContextProvider, MainContextConsumer };