有效路径同时显示有效路径组件和不存在的路径组件

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

当我点击 locathost:3000/faq 或任何其他有效路由时,React 会在页面底部显示有效路由内容和 NotFound(基本上是 404 自定义页面)组件。我只想在命中无效路由时显示 NotFound 组件内容 例如:本地主机: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} />
        }}
      />
    </>
  )
}

注意:我也尝试了以下方法,但没有帮助。仍然显示 NotFound 组件以及有效的路由组件

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} />
        }}
      />
    </>
  )
}

我正在使用“react-router-dom”:“^5.2.0”,

javascript reactjs react-router frontend react-router-dom
1个回答
0
投票

问题

Switch
组件渲染与位置匹配的第一个子
<Route>
<Redirect>
。不幸的是,这也导致了它遇到的第一个非
Route
和非
Redirect
子级的渲染,在本例中为
BuildRoutes

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

要记住的要点:

  • 路由器内渲染的所有路由始终包容地匹配和渲染。换句话说,任何与 URL 路径匹配的内容都会被渲染。
  • Switch
    组件中渲染的所有路由都是排他性匹配和渲染的,例如“第一个匹配的孩子......”。

BuildRoutes
组件正在渲染它渲染的路线,因为路线不是直接是
Switch
组件的子级。这意味着在
NotFound
上渲染的
path="*"
组件将始终匹配并始终被渲染。

解决方案

Switch
移入
BuildRoutes
,以便直接将路由渲染为子级,这样就可以应用 独占 路由匹配和渲染。

<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>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.