- React Material:UI Cookbook
- Adam Boduch
- 345字
- 2021-06-24 15:49:40
There's more...
There are a couple of improvements that you could make with this example. First, you could show a progress indicator within the panel while the content is loading so that the user knows that something is happening. The second improvement can be made both when the panel expands and when it collapses—this should be avoided.
Let's start with the progress indicator. For this, you'll need a utility component and a style for the ExpansionPanelDetails component:
const MaybeProgress = ({ loading }) =>
loading ? <LinearProgress /> : null;
const useStyles = makeStyles(theme => ({
panelDetails: { flexDirection: 'column' }
}));
The MaybeProgress component takes a loading property that, when true, results in a LinearProgress component. Otherwise, nothing is rendered. The flexDirection style is set to column; otherwise, the LinearProgress component won't display. Now let's modify the markup rendered by LazyLoadingPanelContent so it uses these two additions:
return (
<Fragment>
{panels.map((panel, index) => (
<ExpansionPanel key={index} onChange={onChange(index)}>
<ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
<Typography>{panel.title}</Typography>
</ExpansionPanelSummary>
<ExpansionPanelDetails className={classes.panelDetails}>
<MaybeProgress loading={!panel.content} />
<Typography>{panel.content}</Typography>
</ExpansionPanelDetails>
</ExpansionPanel>
))}
</Fragment>
);
The panelDetails class is now used by the ExpansionPanelDetails component. The first child of this component is now MaybeProgress. The loading property is true until the API call populates the content state for the given panel. This means that the progress indicator will be visible until the content loads.
Here's what the first panel looks like when expanded, before the content has loaded:

Once loaded, the content is rendered in place of the progress indicator. Finally, let's make sure that the API call to load content isn't made when the panel is collapsing. This requires an adjustment to the onChange() handler:
const onChange = index => (e, expanded) => {
if (!panels[index].content && expanded) {
fetchPanelContent(index).then(content => {
const newPanels = [...panels];
newPanels[index] = { ...newPanels[index], content };
setPanels(newPanels);
});
}
};
The second argument passed to this function, expanded, tells you whether or not the panel is expanding. If this value is false, you know that the panel is collapsed and that the API call shouldn't be made. This condition has been added to look for content that has already been loaded for the panel.