当我点击locathost:3000/faq或任何其他有效路由时,React会在页面底部显示有效路由内容和NotFound(基本上是404自定义页面)组件.我希望仅在遇到无效路由时才显示NotFound组件内容 Ex: localhost:3000/not-existing-url

const routes = [
  {
    path: '/',
    component: HomePage,
    is_private: false,
  },
  {
    path: '/faq',
    component: RedirectFaqToSupport,
    is_private: false,
  },
  {
    path: '/about-us',
    component: About,
    is_private: false,
  },
  {
    path: '/contact-us',
    component: Contact,
    is_private: false,
  },
 {
    component: NotFound,
    is_private: false,
    path: '*'
  },
]

这是我的App.js组件代码.

class App extends Component {
  constructor() {
    super()
    this.state = {
      redirectToReferrer: false, // may not need this anymore
    }
  }

  render() {
    const { isMobile } = this.props

    const renderLoader = () => (
      <Columns.Column size={12}>
        <div className="has-text-centered" style={{ marginTop: '15%' }}>
          <i className="fas fa-3x fa-cog fa-spin"></i>
        </div>
      </Columns.Column>
    )

    return (
      <Suspense fallback={renderLoader()}>
        <BrowserRouter>
          <Provider>
            <ScrollToTop />
            <Subscribe to={[AppContainer]}>
              {(auth) => {
                return (
                  <>
                    <Header
                      isAuth={auth.state.isAuth}
                      modalViewType={auth.state.modalViewType}
                      unreadMessageCount={auth.state.unreadMessageCount}
                      auth={auth}
                    />
                    <ErrorBoundary>
                      <div className="page-master-container">
                        <Switch>
                          <BuildRoutes
                            isMobile={isMobile}
                            isAuth={auth.state.isAuth}
                            auth={auth}
                          />
                        </Switch>
                      </div>
                    </ErrorBoundary>
                    <Footer isAuth={auth.state.isAuth} />
                  </>
                )
              }}
            </Subscribe>
          </Provider>
        </BrowserRouter>
      </Suspense>
    )
  }
}

以下是BuidRoutes个部件代码

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={(props) =>
      rest.isAuth === true ? (
        <Component {...props} {...rest} />
      ) : (
        <Redirect
          to={{
            pathname: '/login',
            state: { from: props.location },
          }}
        />
      )
    }
  />
)

export const BuildRoutes = ({ isMobile, isAuth, auth }) => {
  const location = useLocation()

  useEffect(() => {
    const queryParams = QueryString.parse(location.search)
    setFeatureFlag(queryParams)
  }, [location])

  return (
    <>
      {routes.map(
        ({ path, component: Component, is_private, is_mother }, key) =>
          !is_private ? (
           
              <Route
                exact={is_mother ? false : true}
                path={path}
                key={key}
                render={(props) => (
                  <Component
                    {...props}
                    isMobile={isMobile}
                    isAuth={isAuth}
                    auth={auth}
                  />
                )}
              />
           
          ) : (
            
              <PrivateRoute
              isAuth={isAuth}
              isMobile={isMobile}
              auth={auth}
              exact={is_mother ? false : true}
              path={path}
              key={key}
              component={Component}
            />
    
            
          )
      )}
      <Route
        exact
        path="/brand/:brandName"
        render={(props) => {
          const { brandName } = props.match.params
          if (bikeBrands.includes(brandName)) {
            return <Redirect to={`/brand/${brandName}-rental`} />
          }
          return <BrandLandingPage brandName={brandName} />
        }}
      />
    </>
  )
}

注:我也try 了下面的方法,但没有帮助.仍显示未找到组件和有效路径组件

export const BuildRoutes = ({ isMobile, isAuth, auth }) => {
  const location = useLocation()

  useEffect(() => {
    const queryParams = QueryString.parse(location.search)
    setFeatureFlag(queryParams)
  }, [location])

  return (
    <>
      {routes.map(
        ({ path, component: Component, is_private, is_mother }, key) =>
          !is_private ? (
            <Route
              exact={is_mother ? false : true}
              path={path}
              key={key}
              render={(props) => (
                <Component
                  {...props}
                  isMobile={isMobile}
                  isAuth={isAuth}
                  auth={auth}
                />
              )}
            />
          ) : (
            <PrivateRoute
              isAuth={isAuth}
              isMobile={isMobile}
              auth={auth}
              exact={is_mother ? false : true}
              path={path}
              key={key}
              component={Component}
            />
          )
      )}
      <Route
        component={NotFound}
      />
      <Route
        exact
        path="/brand/:brandName"
        render={(props) => {
          const { brandName } = props.match.params
          if (bikeBrands.includes(brandName)) {
            return <Redirect to={`/brand/${brandName}-rental`} />
          }
          return <BrandLandingPage brandName={brandName} />
        }}
      />
    </>
  )
}

I am using "react-router-dom": "^5.2.0",

推荐答案

Issue

Switch组件呈现与该位置匹配的第一个子对象<Route><Redirect>.这会产生一个不幸的结果,也就是它遇到的第一个非Route和非Redirect的子代,在本例中为BuildRoutes.

<Switch>
  <BuildRoutes // <-- first child/match and always rendered
    isMobile={isMobile}
    isAuth={auth.state.isAuth}
    auth={auth}
  />
</Switch>

要记住的要点:

  • 路由内呈现的所有路由始终是100匹配和呈现的.换句话说,将呈现与URL路径匹配的任何内容.
  • Switch组件内呈现的所有路由都是101匹配和呈现的,例如"第一个匹配子...".

由于路由104直接是Switch组件的子组件,因此BuildRoutes组件包含地呈现其所呈现的路由.这意味着在path="*"上渲染的NotFound组件将始终匹配并且始终被渲染.

Solution

移动Switch into BuildRoutes,使其直接将路由渲染为子路径,从而可以应用102路由匹配和渲染.

<ErrorBoundary>
  <div className="page-master-container">
    <BuildRoutes
      isMobile={isMobile}
      isAuth={auth.state.isAuth}
      auth={auth}
    />
  /div>
</ErrorBoundary>
const PrivateRoute = ({ isAuth, ...props }) => {
  const from = useLocation();

  return isAuth
    ? <Route {...props} />
    : <Redirect to={{ pathname: '/login', state: { from } }} />;
};
export const BuildRoutes = ({ isMobile, isAuth, auth }) => {
  const location = useLocation();

  useEffect(() => {
    const queryParams = QueryString.parse(location.search);
    setFeatureFlag(queryParams);
  }, [location]);

  return (
    <Switch>
      {routes.map(({ path, component, is_private, is_mother }) => {
        const ChildRoute = is_private ? PrivateRoute : Route;
        const Component = component;

        return (
          <ChildRoute
            key={path}
            exact={!is_mother}
            path={path}
            render={(props) => (
              <Component {...props} {...{ isMobile, isAuth, auth }} />
            )}
          />
        );
      })}
      <Route
        exact
        path="/brand/:brandName"
        render={(props) => {
          const { brandName } = props.match.params
          if (bikeBrands.includes(brandName)) {
            return <Redirect to={`/brand/${brandName}-rental`} />
          }
          return <BrandLandingPage brandName={brandName} />
        }}
      />
    </Switch>
  );
};

Javascript相关问答推荐

如何将拖放功能添加到我已自定义为图像的文件输入HTML标签中?

RxJS setTimeout操作符等效

我无法在NightWatch.js测试中获取完整的Chrome浏览器控制台日志(log)

如何才能拥有在jQuery终端中执行命令的链接?

在grafana情节,避免冲突的情节和传说

将本机导航路由react 到导航栏中未列出的屏幕?

构造HTML表单以使用表单数据创建对象数组

在open shadow—root中匹配时,使用jQuery删除一个封闭的div类

编辑文本无响应.onClick(扩展脚本)

如何修复我的数据表,以使stateSave正常工作?

如何使用JavaScript拆分带空格的单词

使用getBorbingClientRect()更改绝对元素位置

如何在 Select 文本时停止Click事件?

在画布中调整边上反弹框的大小失败

从逗号和破折号分隔的给定字符串中查找所有有效的星期几

react 路由如何使用从加载器返回的数据

为什么我不能使用其同级元素调用和更新子元素?

如何在Java脚本中并行运行for或任意循环的每次迭代

P5play SecurityError:无法从';窗口';读取命名属性';Add';:阻止具有源的帧访问跨源帧

每隔一行文本段落进行镜像(Boustrophedon)