React-Router: Как мне добавить новый компонент и направить его на этапы адаптации в мастере? - PullRequest
2 голосов
/ 05 июля 2019

Хорошо, я немного проясняю этот вопрос в надежде, что кто-то может мне здесь помочь.

Итак, в этом проекте, с которым я работаю, есть мастер адаптации, в основном некоторый код для пошагового процесса адаптации, почти аналогичный тому, что вы видите здесь:

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/, аналогично тому, как в папке редукторов будет находиться корневой файл-редуктор для экспорта всех из них, компонент шагов в этом случае похож на так:

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;
  }
}

Ответы [ 2 ]

1 голос
/ 07 июля 2019

URL-адрес пути отображается на бэкэнде с использованием Entity Framework, аналогично настройке, которую вы можете просмотреть здесь в этой документации:

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
      }
    },
1 голос
/ 05 июля 2019

Я думаю, что первый метод загружает элемент только тогда, когда это необходимо. Второй метод загружает все методы каждый раз. Зачем загружать домой, когда вы находитесь в / Продукты?

...