Como ativar a etapa visitada?
Estou fazendo um aplicativo react simples e incluí uma biblioteca react-stepper-horizontal e tudo bem.
Exemplo de trabalho:
Código apropriado relacionado ao stepper:
const Form = () => {
.
.
.
const [currentPage, setCurrentPage] = useState(1);
const sections = [
{ title: 'Basic Details', onClick: () => setCurrentPage(1) },
{ title: 'Employment Details', onClick: () => setCurrentPage(2) },
{ title: 'Review', onClick: () => setCurrentPage(3) },
];
<Stepper
steps={sections}
activeStep={currentPage}
activeColor="red"
defaultBarColor="red"
completeColor="green"
completeBarColor="green"
/>
.
.
.
}
Etapas para reproduzir o problema:
-> Existem no total três etapas 1,2,3e cada uma tem seções diferentes como Basic Details, Employment Detailse Reviewrespectivamente.
-> Agora, se o usuário inserir qualquer um dos campos de entrada na Etapa 1 e for para a Etapa 2 e preencher alguns campos de entrada lá e ir para a Etapa 3 para revisá-lo e se ele voltar para a Etapa 1 novamente, o estado ativo é perdido em Etapa 3.
-> Agora, a questão é: se queremos ir para a etapa 3, precisamos dar três etapas novamente para chegar à última etapa 3.
Requerimento:
-> Se o usuário uma vez visitou qualquer etapa, então se ele vier para qualquer etapa anterior, todas as etapas que ele visitou anteriormente precisam estar ativas.
Por exemplo:
-> Se o usuário Step 1acessou, usando o botão próximo, ele acessa o Step 3e se deseja voltar para Step 1modificar algumas entradas e novamente se deseja ir para Step 3a etapa de revisão, deve ser possível clicando no Step 3porque ele já visitou essa etapa.
Por favor, ajude-me a alcançar o resultado de tornar as etapas no estado ativo até as quais o usuário visita. Se o usuário visitar a Etapa 3 e voltar à etapa 1 ao clicar no círculo da Etapa 1, então deve haver a possibilidade de voltar à Etapa 3 novamente porque ele já visitou a Etapa 3 ..
Qualquer solução sem qualquer biblioteca também é bem-vinda.
Este é um grande problema se tivermos mais etapas (por exemplo, 7 etapas). Então, por favor, me ajude .. Muito obrigado antecipadamente ..
Respostas
Aqui está uma implementação simples do <Stepper />componente em questão. A chave é ter um trackerque rastreie as etapas visitadas internamente e persista essa informação em re-renderizações.
Demoboard Playground
const { useState, useEffect, useMemo } = React;
const cx = classNames;
function range(a, b) {
return new Array(Math.abs(a - b) + 1).fill(a).map((v, i) => v + i);
}
function Stepper({ steps, activeStep, children }) {
const count = steps.length;
const listOfNum = useMemo(() => range(1, count), [count]);
const tracker = useMemo(() => {
let highestStep = 0;
function hasVisited(step) {
return highestStep >= step;
}
function addToBackLog(step) {
if (step > highestStep) highestStep = step;
}
return {
hasVisited,
addToBackLog,
getHighestStep() {
return highestStep;
},
};
}, []);
tracker.addToBackLog(activeStep);
const noop = () => {};
const prevStep = steps[activeStep - 2];
const currentStep = steps[activeStep - 1];
const nextStep = steps[activeStep];
return (
<div>
<div>
{" "}
{listOfNum.map((num, i) => {
const isActive = activeStep == num;
const isVisited = tracker.hasVisited(num);
const isClickable = num <= tracker.getHighestStep() + 1 || isVisited;
return (
<div
key={num}
className={cx("circle", {
active: isActive,
visited: isVisited,
clickable: isClickable,
})}
onClick={isClickable ? steps[i].onClick : noop}
>
{num}{" "}
</div>
);
})}{" "}
</div>{" "}
<h2> {currentStep && currentStep.title} </h2> <div> {children} </div>{" "}
<div className="footer">
{" "}
{prevStep ? (
<button onClick={prevStep.onClick}> prev </button>
) : null}{" "}
{nextStep ? <button onClick={nextStep.onClick}> next </button> : null}{" "}
</div>{" "}
</div>
);
}
function App() {
const [currentPage, setCurrentPage] = useState(1);
const sections = [
{
title: "Un",
onClick: () => setCurrentPage(1),
},
{
title: "Deux",
onClick: () => setCurrentPage(2),
},
{
title: "Trois",
onClick: () => setCurrentPage(3),
},
{
title: "Quatre",
onClick: () => setCurrentPage(4),
},
{
title: "Cinq",
onClick: () => setCurrentPage(5),
},
];
return (
<Stepper steps={sections} activeStep={currentPage}>
I 'm page {currentPage}{" "}
</Stepper>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
body {
color: #0f0035;
padding-bottom: 2rem;
}
.circle {
display: inline-flex;
height: 2em;
width: 2em;
align-items: center;
justify-content: center;
border-radius: 50%;
background-color: lightgrey;
margin: 0 0.5em;
color: white;
cursor: not-allowed;
}
.active {
background-color: rgba(50, 50, 250) !important;
}
.visited {
background-color: rgba(50, 50, 250, 0.5);
}
.clickable {
cursor: pointer;
}
.footer {
margin-top: 1em;
display: flex;
justify-content: space-between;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.2.6/index.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>