页面未呈现;在 react-router-dom 中使用受保护的路由将道具传递给孩子时

Posted

技术标签:

【中文标题】页面未呈现;在 react-router-dom 中使用受保护的路由将道具传递给孩子时【英文标题】:Page not rendering; When passing props to children using protected routes in react-router-dom 【发布时间】:2020-03-12 01:10:04 【问题描述】:

我正在尝试使用 react-router-dom 创建受保护的路由。

奇怪的是错误说:

元素类型无效:应为字符串(用于内置组件) 或类/函数(用于复合组件)但得到:对象。

检查Context.Consumer的渲染方法。

这就是堆栈跟踪——奇怪的是关于期望字符串的错误?我不是在history.push 中传递"/profile" 吗??

我说这很奇怪的原因是因为在开发工具的控制台中我得到了这个:

index.js:1 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: <Connect(withRouter(LinkNavWithLayout)) />. Did you accidentally export a JSX literal instead of a component?
    in Route (created by PrivateRoute)
    in PrivateRoute (created by App)
    in Switch (created by App)
    in App (created by Context.Consumer)
    in withRouter(App) (created by Connect(withRouter(App)))
    in Connect(withRouter(App)) (created by MyApp)
    in Container (created by MyApp)
    in PersistGate (created by MyApp)
    in Provider (created by MyApp)
    in MyApp (created by AppWithReactRouter)
    in Router (created by BrowserRouter)
    in BrowserRouter (created by AppWithReactRouter)
    in AppWithReactRouter (created by AppWithRedux)
    in AppWithRedux
    in Suspense (created by AppContainer)
    in Container (created by AppContainer)
    in AppContainer

对我来说这更有意义,因为我觉得问题出在受保护的路由组件中,即意味着我的受保护路由功能中的逻辑或我使用它的方式......

  const PrivateRoute = ( component: Component, children, ...rest ) => (
   <Route ...rest render=props => 
    console.log("In PrivateRoute isLoggedIn ", isLoggedIn);
    return isLoggedIn === true
    ? <Component ...props >children</Component>
    : <Redirect to='/' />
    />
  )

这就是我使用它的方式。

return (
    <>
    <Switch>
     <Route
      path='/'
      exact
      render=(props) => <LinkNavWithLayout ...props data=navBars><Index ...props /></LinkNavWithLayout> />

     <Route
      path='/login'
      render=(props) => <Login ...props />
     />

     <Route
      path='/register'
      render=(props) => <Register ...props />
     />

     <PrivateRoute
      path='/profile'
      isLoggedIn=isLoggedIn
      component=
       <LinkNavWithLayout data=navBars><Profile /></LinkNavWithLayout>
      
     />

     <PrivateRoute
      path='/dashboard'
      isLoggedIn=isLoggedIn
      component=
       <LinkNavWithLayout data=navBars><Dashboard /></LinkNavWithLayout>
      
     />
     /* <Route component=()=> <h1>Not found</h1> /> */
    </Switch>
    </>
  )
 

那么为什么我的页面根本没有呈现,这两个错误有什么关系呢?任何帮助将不胜感激!

更新

我添加了 fosso 的建议...

const PrivateRoute = ( component, isLoggedIn, ...rest ) => (
   <Route ...rest render=props => 
    console.log("In PrivateRoute isLoggedIn ", isLoggedIn);
    return isLoggedIn === true
     ?  component 
     : <Redirect to='/' />
    />
  )

  return (
    <>
    <Switch>
     <Route
      path='/'
      exact
      render=(props) => <LinkNavWithLayout ...props data=navBars><Index ...props /></LinkNavWithLayout> />

     <Route
      path='/login'
      render=(props) => <Login ...props />
     />

     <Route
      path='/register'
      render=(props) => <Register ...props />
     />

     <PrivateRoute
      path='/profile'
      isLoggedIn=isLoggedIn
      component=( children ) => ( // not sure where you're planning on passing `children` from `PrivateRoute`
       <LinkNavWithLayout data=navBars><Profile /></LinkNavWithLayout>
      )
     />

     <PrivateRoute
      path='/dashboard'
      isLoggedIn=isLoggedIn
      component=(children) => ( // not sure where you're planning on passing `children` from `PrivateRoute`
       <LinkNavWithLayout data=navBars><Dashboard /></LinkNavWithLayout>
      )
   />
     /* <Route component=()=> <h1>Not found</h1> /> */
    </Switch>
    </>
  )
 

但现在出现以下错误:

Objects are not valid as a React child (found: object with keys component). If you meant to render a collection of children, use an array instead.
    in Route (created by PrivateRoute)
    in PrivateRoute (created by App)
    in Switch (created by App)
    in App (created by Context.Consumer)
    in withRouter(App) (created by Connect(withRouter(App)))
    in Connect(withRouter(App)) (created by MyApp)
    in Container (created by MyApp)
    in PersistGate (created by MyApp)
    in Provider (created by MyApp)
    in MyApp (created by AppWithReactRouter)
    in Router (created by BrowserRouter)
    in BrowserRouter (created by AppWithReactRouter)
    in AppWithReactRouter (created by AppWithRedux)
    in AppWithRedux
    in Suspense (created by AppContainer)
    in Container (created by AppContainer)
    in AppContainer
▶ 30 stack frames were collapsed.
callback

仍然指向...

【问题讨论】:

开场&lt;&gt; 和闭幕&lt;/&gt; 在你的回报中做什么?这是哪个班的? @sallf 这是 React.Fragment 的简写。所以你不必到处都有非语义 ..但是我认为它无论如何都会呈现为 LOL 【参考方案1】:

我发现了一些问题。

component 需要是一个函数,在您的情况下,您传递的是一个 React 元素。

在你的情况下,这可能有效:

<PrivateRoute
   path='/dashboard'
   isLoggedIn=isLoggedIn
   component=(children) => ( // not sure where you're planning on passing `children` from `PrivateRoute`
    <LinkNavWithLayout data=navBars><Dashboard /></LinkNavWithLayout>
   )
/>

作为替代方案,您必须更改 PrivateRoute 组件

const PrivateRoute = ( component, isLoggedIn, ...rest ) => (
 <Route ...rest render=props => 
  console.log("In PrivateRoute isLoggedIn ", isLoggedIn);
  return isLoggedIn === true
  ? component
  : <Redirect to='/' />
  />
  )

但你真的应该把它作为一个单独的组件。

在第二个示例中,您将从父级实例化 JSX,这可能并不理想。 在第一种情况下,component 会在每次重新渲染时生成,这可能不是必需的。

编辑:完整示例

const 
  HashRouter,
  Switch,
  Route,
  Link
 = ReactRouterDOM

const Page2 = () => (
  <div>
    <h1>Page2</h1>
  </div>
)

const Page1 = () => (
  <div>
    <h1>Page1</h1>
  </div>
)

const Home = () => (
  <div>
    <h1>Home</h1>
  </div>
)

const PrivateRoute = (component: Component, isLoggedIn, ...rest) => (<Route ...rest render=props => isLoggedIn ? <Component /> : <div>Not logged in</div> />)

const Content = () => (
  <main>
    <Switch>
      <Route exact path='/' component=Home/>
      <PrivateRoute path='/page1' isLoggedIn component=Page1/>
      <PrivateRoute path='/page2' isLoggedIn=false component=Page2/>
    </Switch>
  </main>
)

const Nav = () => (
  <header>
    <nav>
      <ul>
        <li><Link to='/'>Home</Link></li>
        <li><Link to='/page1'>Page 1 (logged in)</Link></li>
        <li><Link to='/page2'>Page 2 (not logged in)</Link></li>
      </ul>
    </nav>
  </header>
)

const App = () => (
  <div>
    <Nav />
    <Content />
  </div>
)

ReactDOM.render((
  <HashRouter>
    <App />
  </HashRouter>
), document.getElementById('root'))

在代码笔中测试。抱歉,但如果还有更多错误,我认为我没有足够的信息来进一步调试。我建议发布另一个带有完整示例的问题。

【讨论】:

您的建议似乎产生了不同的错误! 对不起,如果我的评论令人困惑,但我概述了 2 个不同的解决方案,无需更改这两个组件。更改PrivateRouteRouter 层次结构。

以上是关于页面未呈现;在 react-router-dom 中使用受保护的路由将道具传递给孩子时的主要内容,如果未能解决你的问题,请参考以下文章

页面在刷新时不加载 - react-router-dom

react-router-dom 路由组件需要页面重新加载

在 react 中转换为 .tsx 后,组件未呈现任何记录

反应路由器或链接未呈现

使用 react-router-dom 成功认证后将用户重定向到他们请求的页面

当我的路线放置在子组件中时,url正在更改但组件未呈现