0

我正在尝试发布一个名为“React-Animated-FullScreen-SideNavBar”的 Npm 包,它具有开箱即用的 react-routing 功能。如果您查看演示,到目前为止,一切都已设置好并且运行良好。

演示链接:- https://aryan21710.github.io/reactFullScreenAnimatedSideNavbar-github.io/

一旦我通过执行 npm 链接在内部测试包,我就会不断收到以下错误“不变式失败:您不应该在路由器外部使用 NavLink”

为了克服这个问题,我将 Navlink 包装在 Router 标记内,并带有指向 createBrowserHistory() 的历史记录。尽管如此,当我单击侧导航栏中的任何链接时,路由停止工作,并且我不再被重定向到指向 url 的组件。

我将非常感谢这方面的帮助。

包 repo 的链接:- https://github.com/aryan21710/reactFullScreenAnimatedSideNavbar-github.io

从包中导出的 React 组件在 App.js 中调用如下。

import React from "react";
import CreateSideBarNavLink from "react-animated-fullscreen-sidenavbar";

const App = () => {
  const myData = {
    navBarSettings: {
      navBarWidth: "100vw",
      theme: {
        primaryColor: "rgb(0, 51, 153,0.4)",
        secondaryColor: "rgb(0, 85, 255)",
        toggleButtonColor: "rgb(0, 51, 153,1)",
      },
    },
    userInfo: {
      name: "aryan sharma",
      email: "aryan@gmail.com",
    },

    link1: {
      IconSet: <i className="fa fa-fw fa-list" style={{ fontSize: window.innerWidth > 768 ? "1vw" : "4vw" }} />,
      Text: "Products",
      Expandable: true,
      ExpandableIconset: (
        <i
          className="fas fa-angle-right angleIcon"
          style={{ fontSize: window.innerWidth > 768 ? "1vw" : "4vw" }}
        />
      ),

      Route: "/products",
      children: [
        {
          IconSet: <i className="fas fa-gavel" style={{ fontSize: window.innerWidth > 768 ? "1vw" : "4vw" }}></i>,
          Text: "Product1",
          Expandable: false,
          children: null,
          Route: "/products/product1",
        },


      ],
    },

and more links data....

  return (
    <React.Fragment>
      <CreateSideBarNavLink myData={myData} />
    </React.Fragment>
  );
};

export default App;

负责制作提供 SideNavigation 功能以及反应路由的包的组件如下。

import React, { Component } from "react";
import { NavLink, Router } from "react-router-dom";
import "../../../node_modules/@fortawesome/fontawesome-free/css/all.css";
import UserInfoGrid from "./UserInfoGrid";
import "../../styles/index.css";
import { createBrowserHistory } from "history";
import {withRouter} from 'react-router-dom';

class CreateSideBarNavLink extends Component {
  state = {
    slide: styles.sideBarWrapper,
    whichLinkToToggle: [],
    linksAndStatus: {},
    toggleBtnStatus: false,
    userStyleSideNavLink: {},
    userStyleToggleBtn: {},
  };

  componentDidMount() {
    this.updateTextArray();
    this.applyUserStyles();
  }

  componentDidUpdate(prevProps, prevState) {
    const { toggleBtnStatus } = this.state;
    if (prevState.toggleBtnStatus !== toggleBtnStatus) {
      this.toggleClassForSideBar();
    }
  }

  toggleClassForSideBar = () => {
    const { toggleBtnStatus, userStyleSideNavLink } = this.state;
    if (toggleBtnStatus) {
      this.setState({
        slide: { ...styles.slideOutSideBar, ...userStyleSideNavLink },
      });
    } else {
      this.setState({ slide: styles.slideInSideBar });
    }
  };

  onExpand = (linkText, children) => {
    const { theme } = this.props.myData.navBarSettings;
    const { linksAndStatus } = this.state;
    this.setState({
      whichLinkToToggle: linkText,
    });

    const myobj = {};
    const childrenLinkWrapperHeight = 4 * children.length + "vh";
    for (let i in linksAndStatus) {
      const _ = {};

      if (i === linkText) {
        _["toggle"] = !linksAndStatus[i]["toggle"];
        _["rotateIcon"] = _["toggle"] ? styles.expandIcon : styles.collapseIcon;
        _["childLinkWrapper"] = _["toggle"]
          ? {
              ...styles.expandChildren,
              background: theme.secondaryColor,
              height: childrenLinkWrapperHeight,
            }
          : { ...styles.collapseChildren, background: theme.secondaryColor };

        myobj[i] = _;
      } else {
        _["toggle"] = linksAndStatus[i]["toggle"] === true ? false : false;
        _["rotateIcon"] = _["toggle"] ? styles.expandIcon : styles.collapseIcon;
        _["childLinkWrapper"] = _["toggle"]
          ? styles.expandChildren
          : styles.collapseChildren;
        myobj[i] = _;
      }
    }
    this.setState({
      linksAndStatus: myobj,
    });
  };

  updateStyleForToggleIcon = (linkText) => {
    const { linksAndStatus } = this.state;

    for (let i in linksAndStatus) {
      if (i === linkText) {
        return linksAndStatus[i]["rotateIcon"];
      }
    }
  };

  updateStyleForChildLinkWrapper = (linkText) => {
    const { linksAndStatus } = this.state;

    for (let i in linksAndStatus) {
      if (i === linkText) {
        return linksAndStatus[i]["childLinkWrapper"];
      }
    }
  };

  createChildLinks = (children, Text) => {
    const { navBarWidth } = this.props.myData.navBarSettings;

    if (Text === this.state.whichLinkToToggle) {
      const returnData = [];
      children.forEach((_, idx) => {
        returnData.push(
          <div className="childLinkWrapper">
            <div style={{ ...styles.flexStyling, ...styles.iconChildren }}>
              <div
                className={this.updateStyleForChidrenIconAndText(Text)}
                style={styles.childIcon}
              >
                {_.IconSet}
              </div>
            </div>
            <div style={{ ...styles.flexStyling, ...styles.childTextWrapper }}>
              <div
                className={this.updateStyleForChidrenIconAndText(Text)}
                style={styles.childText}
              >
                <NavLink
                activeStyle={styles.navlinks}
                to={_.Route}
                onClick={() => {
                  this.props.history.push('/products')
                  navBarWidth === "100vw" &&
                    this.setState({
                      toggleBtnStatus: !this.state.toggleBtnStatus,
                    });
                }}
              >

                  {" "}
                  {_.Text}
                </NavLink>

              </div>
            </div>
          </div>
        );
      });

      return returnData.map((_) => _);
    }
  };

  updateStyleForChidrenIconAndText = (linkText) => {
    const { linksAndStatus } = this.state;

    for (let i in linksAndStatus) {
      if (i === linkText) {
        return linksAndStatus[i]["childLinkData"];
      }
    }
  };

  updateTextArray = () => {
    const { myData } = this.props;
    const myObj = {};

    for (let i in myData) {
      if (i !== "userInfo" && i !== "navBarSettings") {
        const { Text } = myData[i];
        myObj[Text] = {
          toggle: false,
          rotateIcon: styles.collapseIcon,
          childLinkWrapper: styles.collapseChildren,
        };
      }
    }

    this.setState({
      linksAndStatus: myObj,
    });
  };

  applyUserStyles = (props) => {
    const { navBarWidth, theme } = this.props.myData.navBarSettings;
    const newStyle = {};

    const validateWidth =
      Number(navBarWidth.replace("vw", "")) < 20 ? "20vw" : navBarWidth;

    newStyle["width"] =
      validateWidth !== styles.sideNavBarLinks.width
        ? validateWidth
        : styles.sideNavBarLinks.width;

    newStyle["background"] =
      theme.primaryColor !== styles.sideNavBarLinks.background
        ? theme.primaryColor
        : styles.sideNavBarLinks.background;

    this.setState({
      userStyleSideNavLink: newStyle,
      userStyleToggleBtn: {
        ...styles.toggleBarWrapper,
        background: theme.toggleButtonColor,
      },
    });
  };

  navBarLinksGrid = (props) => {
    const { myData } = this.props;
    const returnData = [];
    const { navBarWidth } = this.props.myData.navBarSettings;


    for (let i in myData) {
      if (i !== "userInfo" && i !== "navBarSettings") {
        const {
          Expandable,
          IconSet,
          Text,
          children,
          Route,
          ExpandableIconset,
        } = myData[i];

        returnData.push(
          <React.Fragment>
            <div
              style={{ ...styles.flexStyling, ...styles.parentLinkWrapper }}
              className="parentLinkWrapper"
            >
              <div
                style={{
                  ...styles.flexStyling,
                  ...styles.parentLinkIconWrapper,
                }}
              >
                <div style={styles.parentLinkIcon}>{IconSet}</div>
              </div>
              <div style={{ ...styles.parentLinkText }}>
              <NavLink
              activeStyle={styles.navlinks}
              to={Route}
              onClick={() => {
                navBarWidth === "100vw" &&
                  this.setState({
                    toggleBtnStatus: !this.state.toggleBtnStatus,
                  });
              }}
            >
              {Text}
            </NavLink>

              </div>

              {Expandable && (
                <div
                  style={this.updateStyleForToggleIcon(Text)}
                  data-value={Text}
                  onClick={() => {
                    this.onExpand(Text, children);
                  }}
                >
                  {" "}
                  {ExpandableIconset}
                </div>
              )}
            </div>
            {Expandable && (
              <div
                className="childLinkWrapper"
                style={this.updateStyleForChildLinkWrapper(Text)}
              >
                {this.createChildLinks(children, Text)}
              </div>
            )}
          </React.Fragment>
        );
      }
    }
    return returnData.map((_) => _);
  };

  render() {



    const { toggleBtnStatus } = this.state;
    const { name, email, lastLogin } = this.props.myData.userInfo;

    return (
        <React.Fragment>
          <div
            style={this.state.userStyleToggleBtn}
            onClick={() => {
              this.setState({
                toggleBtnStatus: !toggleBtnStatus,
              });
            }}
          >
            <span className={toggleBtnStatus ? "hideme " : "bar1"}></span>
            <span className={toggleBtnStatus ? "rotate45 bar2" : "bar2"}></span>
            <span
              className={toggleBtnStatus ? "rotate-45 bar3" : "bar3"}
            ></span>
          </div>
          <div className="SideBarWrapper" style={this.state.slide}>
            <div
              className="sideNavBarLinks"
              style={this.state.userStyleSideNavLink}
            >
              <div style={styles.borderSeparator}>
                <UserInfoGrid name={name} email={email} lastLogin={lastLogin} />
                {this.navBarLinksGrid()}
              </div>
            </div>
          </div>
        </React.Fragment>
    );
  }
}

const styles = {
  toggleBarWrapper: {
    width: window.innerWidth > 768 ? "3.2vw" : "10vw",
    height: "4.6vh",
    lineHeight: "4.6vh",
    cursor: "pointer",
    top: "0vh",
    left: "0vw",
    position: "absolute",
    background: "rgba(255, 102, 0, 0.877)",
    zIndex: "1000",
  },
  sideBarWrapper: {
    position: "absolute",
    top: "0vh",
    left: "-100vw",
    height: "100vh",
    zIndex: "2",
  },
  borderSeparator: {
    width: window.innerWidth > 768 ? "20vw" : "100vw",
    height: "100vh",
    borderRight: "1px solid rgba(255,255,255,0.3)",
  },
  sideNavBarLinks: {
    width: window.innerWidth > 768 ? "20vw" : "100vw",
    height: "100vh",
  },
  slideOutSideBar: {
    width: window.innerWidth > 768 ? "20vw" : "100vw",
    display: " flex",
    flexDirection: " row",
    position: " absolute",
    top: " 0vh",
    left: " -100vw",
    height: " 100vh",
    zIndex: "2",
    animation: " slideOut 0.5s ease-in-out 1 forwards",
  },
  slideInSideBar: {
    position: "absolute",
    top: "0vh",
    height: "100vh",
    zIndex: "2",
    animation: "slideIn 0.5s ease-in-out 1 forwards",
  },
  flexStyling: {
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
  },

  parentLinkWrapper: {
    position: "relative",
    width: window.innerWidth > 768 ? "20vw" : "100vw",
    height: window.innerWidth > 768 ? "5vh" : "9vh",
  },
  parentLinkIconWrapper: {
    position: "absolute",
    left: window.innerWidth > 768 ? "1vw" : "3vw",
    width: window.innerWidth > 768 ? "3vw" : "15vw",
    justifyContent: "flex-end",
  },
  parentLinkIcon: {
    borderRadius: "5px",
    background: "black",
    color: "rgba(255,255,255,0.6)",
    padding: window.innerWidth > 768 ? "0.5vh 0.5vw" : "2vh 2vw",
    boxShadow: " black 0px 0px 4px 0px",
  },
  expandIcon: {
    transform: "rotate(90deg)",
    transition: "transform 0.1s ease-out",
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    position: "absolute",
    left: window.innerWidth > 768 ? "18vw" : "60vw",
    width: window.innerWidth > 768 ? "1vw" : "3vw",
    color: "rgba(255,255,255,0.6)",
  },

  collapseIcon: {
    transform: "rotate(0deg)",
    transition: "transform 0.1s ease-out",
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    position: "absolute",
    left: window.innerWidth > 768 ? "18vw" : "60vw",
    width: window.innerWidth > 768 ? "1vw" : "3vw",
    color: "rgba(255,255,255,0.6)",
  },
  parentLinkText: {
    position: "absolute",
    left: window.innerWidth > 768 ? "4.5vw" : "22vw",
    width: window.innerWidth > 768 ? "12vw" : "40vw",
    fontSize: window.innerWidth > 768 ? "1.1vw" : "5vw",
    color: "rgba(255,255,255,0.6)",
    marginLeft: "10px",
  },
  navlinks: {
    textDecoration: "none",
    color: "rgba(255,255,255,1)",
  },
  parentLinkExpandIcon: {
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    cursor: "pointer",
  },
  error: {
    fontSize: window.innerWidth > 768 ? "1.1vw" : "4.5vw",
    color: "red",
    fontWeight: "900",
  },

  collapseChildren: {
    display: "flex",
    flexDirection: "column",
    justifyContent: "center",
    boxShadow: "black -1px 2px 0px 0px",
    width: window.innerWidth > 768 ? "20vw" : "100vw",
    transition: "height 200ms ease-in",
    color: "rgba(255,255,255,0.6)",
    height: "0vh",
    overflow: "hidden",
  },
  expandChildren: {
    display: "flex",
    flexDirection: "column",
    justifyContent: "center",
    boxShadow: "black -1px 2px 0px 0px",
    width: window.innerWidth > 768 ? "20vw" : "100vw",
    transition: "height 200ms ease-in",
    color: "rgba(255,255,255,0.6)",
    height: "0vh",
    padding: "2vh 0vw",
    overflow: "hidden",
  },

  childTextWrapper: {
    flexDirection: "column",
    justifyContent: "center",
    alignItems: "flex-start",
    color: "rgba(255,255,255,0.6)",
    fontSize: window.innerWidth > 768 ? "1vw" : "4vw",
  },
  iconChildren: {
    flexDirection: "column",
    justifyContent: "center",
    alignItems: "flex-end",
  },
  childText: {
    margin: window.innerWidth > 768 ? " 1vh 0vw 1vh 1vw" : " 1vh 0vw 1vh 5vw",
    fontSize: window.innerWidth > 768 ? "1vw" : "4vw",
    cursor: "pointer",
  },
  childIcon: {
    margin: " 0.5vh 0vw",
    borderRadius: "5px",
    background: "black",
    color: "rgba(255,255,255,0.6)",
    padding: "0.35vh 0.35vw",
    boxShadow: "black 0px 0px 4px 0px",
    fontSize: window.innerWidth > 768 ? "1vw" : "5vw",
  },
};

export default CreateSideBarNavLink;

上面的代码片段是在 AppRoutes.js 中调用 App.js 时的工作代码,如下所示。

class Approutes extends Component {
  render() {
    return (
      <BrowserRouter>
        <div>
          <App />
          <Switch>
            <Route exact={true} strict path="/">
              <Home />
            </Route>
            <Route exact={true} strict path="/products">
              <Product />
            </Route>
            <Route exact={true} strict path="/about">
              <About />
            </Route>
            <Route exact={true} strict path="/portfolio">
              <Portfolio />
            </Route>
            <Route exact={true} strict path="/catelogue">
              <Catelogue />
            </Route>

在 npm 链接之后调用包时出现错误。我调用包的方式是使用 create-react-app 和 index.js 调用 Approutes 创建一个虚拟的 react-app。Approutes 有 BrowserRouter 包装 App.js。App.js 就像一个标头或通用组件(App.js 在 switch 语句之外)。App.js 的调用方式如上所示。

请让我知道我在这里缺少什么?

4

0 回答 0