Open nosyn opened 2 years ago
same problem here, looking for the solution
Did you get any solution?
Someone found a solution please ?
+1 on this.
Yup, gonna have to figure out a different way to get input because mui stepper keeps re-rendering and the input keeps losing focus. Cant believe this is still an issue after 2 years lol.
The CustomStepper
component is a versatile stepper UI built with Material-UI (MUI) that allows you to create a dynamic and interactive step-by-step navigation system. It supports two styles of connectors (qonto
and colorlib
), custom icons for each step, and interactive modals for additional actions.
Problem: When the steps in the stepper are static (i.e., not changing dynamically), the component may re-render more often than necessary, which can affect performance.
Solution: To optimize performance, use a static array for steps instead of dynamically generating it. This approach prevents unnecessary re-renders and improves efficiency.
Define a Static Array for Steps Define the array of steps outside the component to ensure it remains constant and does not trigger re-renders.
const stepsMore = ["D", "O", "E", "R", "-R"];
Update the Component Use the static array inside the component to render the steps.
const CustomStepper = React.memo(function CustomStepper({
steps,
activeStep,
connectorType = "qonto",
icons,
highlightStep,
label_status,
HandleAddRating,
stepColors,
}) {
// Static steps array
const stepsMore = ["D", "O", "E", "R", "-R"];
// ... Rest of the component code
});
Optimize Rendering
Ensure that the Stepper
component only re-renders when necessary by using React.memo
and optimizing prop comparisons.
import React, { useCallback, useMemo, useState } from "react";
import { styled } from "@mui/material/styles";
import Stack from "@mui/material/Stack";
import Stepper from "@mui/material/Stepper";
import Step from "@mui/material/Step";
import StepLabel from "@mui/material/StepLabel";
import Check from "@mui/icons-material/Check";
import StepConnector, { stepConnectorClasses } from "@mui/material/StepConnector";
import DropdownModal from "../DropdownModal/DropdownModal";
import Tooltip from "@mui/material/Tooltip";
// Styles for connectors and step icons
// (Styles as provided above)
// Component definition
const CustomStepper = React.memo(function CustomStepper({
steps,
activeStep,
connectorType = "qonto",
icons,
highlightStep,
label_status,
HandleAddRating,
stepColors,
}) {
const Connector = useMemo(
() => (connectorType === "colorlib" ? ColorlibConnector : QontoConnector),
[connectorType]
);
const StepIconComponent = useMemo(
() => (connectorType === "colorlib" ? ColorlibStepIcon : QontoStepIcon),
[connectorType]
);
const [modalOpen, setModalOpen] = useState(false);
const [selectedIcon, setSelectedIcon] = useState("D");
const handleStepClick = useCallback(
(icon, index) => {
setSelectedIcon(icon);
if (stepColors[index] !== "#4caf50") {
setModalOpen(true);
}
},
[stepColors]
);
const handleClose = useCallback(() => setModalOpen(false), []);
const allStepsCompleted = useMemo(
() => activeStep >= steps.length,
[activeStep, steps.length]
);
const handleSaveRating = useCallback(
(ratingObject) => {
HandleAddRating(ratingObject);
setModalOpen(false);
},
[HandleAddRating]
);
const stepsMore = ["D", "O", "E", "R", "-R"];
return (
<>
{connectorType === "colorlib" ? (
<ColorlibGlobalStyles />
) : (
<GlobalStyles />
)}
<Stack sx={{ width: "100%" }} spacing={4}>
<Stepper
alternativeLabel
activeStep={activeStep}
connector={<Connector stepColor={stepColors[activeStep]} />}
>
{stepsMore.map((label, index) => (
<Step key={label}>
<Tooltip title={steps[index]} arrow>
<span>
<StepLabel
StepIconComponent={(props) => (
<StepIconComponent
{...props}
icon={icons ? icons[index + 1] : undefined}
onClick={() =>
handleStepClick(icons[index + 1], index)
}
highlight={highlightStep === index}
stepColor={stepColors[index]}
allCompleted={allStepsCompleted}
/>
)}
>
<span>{label}</span>
</StepLabel>
</span>
</Tooltip>
</Step>
))}
</Stepper>
</Stack>
<DropdownModal
open={modalOpen}
handleClose={handleClose}
selectedIcon={selectedIcon}
HandleAddRating={handleSaveRating}
step_name={steps[activeStep]}
label_status={label_status}
/>
</>
);
}, (prevProps, nextProps) => {
return (
prevProps.activeStep === nextProps.activeStep &&
prevProps.connectorType === nextProps.connectorType &&
prevProps.highlightStep === nextProps.highlightStep &&
prevProps.label_status === nextProps.label_status &&
JSON.stringify(prevProps.steps) === JSON.stringify(nextProps.steps) &&
JSON.stringify(prevProps.stepColors) ===
JSON.stringify(nextProps.stepColors)
);
});
export default CustomStepper;
Duplicates
Latest version
Current behavior 😯
I'm trying to combine the Vertical Stepper Component with the components that I already had. Something weird happens that whenever I go to the next step, the component inside the
<StepContent>
render twice and it's not happening the first time the component is rendered.Expected behavior 🤔
Better render performance with children elements inside the
<StepContent>
Steps to reproduce 🕹
Codesanbox: https://codesandbox.io/s/verticallinearstepper-material-demo-forked-ossb3?file=/demo.js
Steps:
See
render Test Component
from theconsole
on the first time the web app is loadedClick Continue
See
render Test Component
from theconsole
is called twice this timeContext 🔦
No response
Your environment 🌎
`npx @mui/envinfo`
``` Don't forget to mention which browser you used. Output from `npx @mui/envinfo` goes here. ```