【问题标题】:How to make the visited step active?如何使访问的步骤处于活动状态?
【发布时间】:2020-12-29 18:33:08
【问题描述】:

我正在制作一个简单的反应应用程序并包含react-stepper-horizontal 库,一切都很好。

工作示例:

与步进器相关的适当代码:

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"
/>

.
.
.
}

重现问题的步骤:

-> 共有三个步骤1,2,3,每个步骤都有不同的部分,分别为Basic DetailsEmployment DetailsReview

-> 现在,如果用户在第 1 步中输入任何输入字段并转到第 2 步并在那里填写一些输入字段并转到第 3 步查看它,如果他再次回到第 1 步,则处于活动状态在第 3 步中丢失。

->所以现在问题是,如果我们想进入第 3 步,那么我们需要再次进行 3 步才能到达最后的第 3 步。

要求:

-> 如果用户曾经访问过任何步骤,那么如果他来到之前的任何步骤,那么他之前访问过的所有步骤都需要处于活动状态。

例如:

-> 如果用户登陆Step 1,然后使用下一步按钮,他会到达Step 3,如果他想回到Step 1修改一些输入,如果他想再去Step 3对于审查步骤,那么应该可以通过单击Step 3,因为他已经访问了该步骤。

请帮助我实现使用户访问的步骤处于活动状态的结果。如果用户访问第 3 步并单击第 1 步圆圈返回第 1 步,那么应该有可能回来再次到第 3 步,因为他已经访问了第 3 步..

也欢迎任何没有任何库的解决方案。

如果我们有更多步骤(例如 7 个步骤),这将是一个大问题。所以请帮助我..提前非常感谢..

【问题讨论】:

  • docs好像不支持你想要实现的。 library 也不再开发。这就是为什么在将要使用的库添加到项目之前检查它们如此重要的原因。
  • @bertdida,谢谢你的评论兄弟。是的,你是对的,我也搜索过同样的结果,但最终没有得到积极的结果。你有任何想法自定义代码来实现在步骤上单击事件侦听器的帮助下的结果?
  • 你为什么不放弃那个库并自己实现它呢?这似乎很容易实现。有任何阻塞问题吗?

标签: javascript css reactjs stepper


【解决方案1】:

这里是有问题的&lt;Stepper /&gt; 组件的简单实现。关键是要有一个 tracker 来在内部跟踪访问的步骤,并在重新渲染中保留该信息。

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>

【讨论】:

  • 感谢您的帮助。是否可以在每个步骤之间添加一条水平线,指示绿色表示活动步骤,红色表示下一个非活动步骤?您可以在我在问题中提供的沙箱中看到相同的内容..
  • 我将奖励您的回答。您能否帮我在步骤之间放置一条水平线,正确指示活动和非活动步骤,就像给定的代码框链接一样?谢谢..
  • 我已授予您赏金,但仍要求您提供完整的解决方案,并在每个步骤圆圈之间划线..
  • 啊,好吧。你能告诉我你做了什么努力吗?你在哪里卡住了?
  • 我可以帮助你摆脱困境,但我拒绝只为你编写代码。这不是我的义务,即使有赏金也不是。我以为你对如何解决反应问题没有一个好主意,所以我向你展示了这个想法。这就是你最初问的问题。现在你要求我也做 css 部分。好吧,这不是堆栈溢出的工作方式。您至少必须表现出自己的一些努力,或者提出一个适当的问题,而不是简单地要求人们为您编写代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多