React-Router:如何添加新组件并路由到向导上的入门步骤?

问题描述 投票:0回答:2

我正在处理的这个项目有一个入门向导,基本上是一些处理逐步入门过程的代码,几乎与您在这里看到的类似:

https://medium.com/@l_e/writing-a-wizard-in-react-8dafbce6db07

除了这个据说有一个将组件或步骤转换为路线的功能:

convertStepToRoute = step => {
    const Component = StepComponents[step.component || ''];

    return Component
      ? <Route
          key={step.key}
          path={`${WizardLayout.pathname}/${step.url}`}
          render={this.renderRouteComponent(Component)}
        />
      : null;
  };

StepComponents
来自
import StepComponents from '../Steps';
,这是一个包含所有组件的目录,它们是六个,现在是七个,应该引导用户完成入门过程。

据我所知,它们是从

index.js
目录内的
Steps/
文件中提取的,类似于在 reducers 文件夹中存在用于导出所有文件的根减速器文件,在本例中的步骤组件如下所示:

import glamorous from "glamorous";
import ThemedCard from "../../ThemedCard";
import BusinessAddress from "./BusinessAddress";
import CreatePassword from "./CreatePassword";
import GetInvolved from "./GetInvolved";
import Representatives from "./Representatives";
import Topics from "./Topics";
import MemberBenefits from "./MemberBenefits";

export const StepHeader = glamorous.div({
  marginBottom: 20,
  marginTop: 20,
  fontSize: "2rem",
  color: "#757575"
});

const OnboardingCompleted = glamorous(ThemedCard)({
  textAlign: "center",
  boxShadow: "none !important"
});

export default {
  CreatePassword,
  BusinessAddress,
  Completed: OnboardingCompleted,
  GetInvolved,
  MemberBenefits,
  Topics,
  Representatives
};

好吧,我添加了我的

MemberBenefits
,但它似乎不起作用,它没有使用相应的路线进行渲染。哪里可能无法注册这个新步骤或组件?

好吧,魔法不是发生在

Onboarding/OnBoardingWizard/index.js
内部,而是发生在
Wizard/WizardEngine.js
内部:

import React from "react";
import PropTypes from "prop-types";
import objectToArray from "../../../../common/utils/object-to-array";

// TODO: figure out how to use this without making children of wizard engine tied to wizardStep
// eslint-disable-next-line no-unused-vars
class WizardStep {
  constructor({ component, color, order, render }, stepComponents) {
    if (!component || !render) {
      throw new Error("Component or render must be provided.");
    }

    let componentValue;
    if (component) {
      componentValue = this.resolveComponent(component, stepComponents);
      if (!!componentValue && !React.isValidElement(componentValue)) {
        throw new Error(
          "wizard step expected component to be a valid react element"
        );
      }
    } else if (render && typeof render === "function") {
      throw new Error("wizard step expected render to be a function");
    }

    this.Component = componentValue;
    this.color = color;
    this.order = order;
    this.render = render;
  }

  resolveComponent = (component, stepComponents) => {
    const componentValue = component;

    if (typeof component === "string") {
      const componentValue = stepComponents[component];
      if (!componentValue) {
        throw new Error("component doesnt exist");
      }
    }

    return componentValue;
  };
}

export default class WizardEngine extends React.Component {
  static propTypes = {
    steps: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
    initActiveIndex: PropTypes.oneOfType([PropTypes.func, PropTypes.number]),
    stepComponents: PropTypes.object
  };

  constructor(props) {
    super(props);
    this.state = {
      activeIndex: this.resolveInitActiveIndex(props),
      steps: this.buildStepsFromConfig(props)
    };
  }

  componentWillReceiveProps(nextProps) {
    this.setState({ steps: this.buildStepsFromConfig(nextProps) });
  }

  resolveInitActiveIndex = props => {
    const { initActiveIndex } = props;
    let activeIndex = 0;

    if (typeof initActiveIndex === "function") {
      activeIndex = initActiveIndex(props);
    }

    if (typeof initActiveIndex === "number") {
      activeIndex = initActiveIndex;
    }

    return activeIndex;
  };

  buildStepsFromConfig = props => {
    const { steps } = props;
    let stepArr = steps;

    // validate stepList
    if (typeof steps === "object" && !Array.isArray(steps)) {
      stepArr = objectToArray(steps);
    }

    if (!Array.isArray(stepArr)) {
      throw new Error(
        `Unsupported Parameter: Wizard Engine(steps) expected either (object, array); got ${typeof stepArr}`
      );
    }

    return stepArr;

    // return stepArr.map(step => new WizardStep(step));
  };

  setActiveIndex = activeIndex => {
    this.setState({ activeIndex });
  };

  goForward = () => {
    this.setState(prevState => ({
      activeIndex: prevState.activeIndex + 1
    }));
  };

  goBack = () => {
    this.setState(prevState => ({
      activeIndex: prevState.activeIndex - 1
    }));
  };

  render() {
    const { children } = this.props;
    const childProps = {
      ...this.state,
      setActiveIndex: this.setActiveIndex,
      goForward: this.goForward,
      goBack: this.goBack,
      currentStep: this.state.steps[this.state.activeIndex]
    };

    if (Array.isArray(children)) {
      return (
        <div>
          {children.map((child, i) => {
            if (typeof child === "function") {
              return child(childProps);
            }
            childProps.key = `${child.type.name}_${i}`;
            return React.cloneElement(child, childProps);
          })}
        </div>
      );
    }

    if (typeof children === "function") {
      return children(childProps);
    }

    return children;
  }
}
reactjs react-router react-router-dom
2个回答
1
投票

我认为第一种方法仅在需要时加载元素。 第二种方法每次都加载所有方法。为什么在 /Products 时要加载首页?


1
投票

路径 URL 正在利用实体框架映射到后端,类似于您可以在本文档中查看的设置:

https://dzone.com/articles/aspnet-core-crud-with-reactjs-and-entity-framework

除非它是通过 Express 完成的。

因此,它并不是在传统意义上使用 React-Router,其中 Express 允许它控制到组件的整个映射路由路径,而是将入门组件的路径映射到 Express 内部

src/app-server/apiConfig.js
,如下所示:

"get-involved-onboarding": {
      title: "Get Involved",
      url: "/account/onboarding/get-involved",
      icon: "explore",
      component: "GetInvolved",
      progress: {
        stepType: "GetInvolved",
        hasCompleted: true
      }
    },
© www.soinside.com 2019 - 2024. All rights reserved.