簡體   English   中英

子頁面與react-router 4不匹配

[英]subpage doesn't match react-router 4

我有這樣的路由器設置

<Switch>
  <PrivatePage key={index} {...opts} component={(props) => 
     <Section {...props} pages={childRoutes} />
  } />
  <PrivatePage path='/accounts/:id' exact={true}  render={({ match }) => (
    <Redirect to={/accounts/${match.params.id}/profile} />
  )} />
  ...
  <Route component={NotFound} />
</Switch>

然后<Section />

<SubNavMenu />
<Route path=/accounts/:id/profile componet={ProfilePage} />
<Route path=/accounts/:id/dashboard componet={DashboardPage} />

然后<PrivatePage />呈現類似,而<Page />只是呈現<Navigation /> {this.props.children}

const PrivatePage = ({ component: Component, ...rest }) => {
  let result = props => (
    <Redirect
      to={{
        pathname: '/redirect',
        state: { from: props.location },
      }}
    />
  )

  if (User.methods.isAuthed()) {
    result = props => (
      <Page>
        <Component {...props} />
      </Page>
    )
  } else if (rest.path === '/') {
    result = props => (
      <Redirect
        to={{
          pathname: '/login',
        }}
      />
    )
  }

  return <Route {...rest} render={props => result(props)} />
}

export default PrivatePage

單擊將我帶到accounts/:id的鏈接可以正確地將我重定向到配置文件頁面,但是當我嘗試從SubNavMenu轉到儀表板頁面時,我得到了NotFound頁面並安慰this.props.match {path: "/", url: "/", params: {…}, isExact: false}但我的路徑是/accounts/7kB7fRdsu39Be44ou/dashboard

謝謝您的幫助


根據要求,提供本節的完整代碼

pages = [
{
  authed: true,
  icon: 'cog',
  component: (<div/>),
  name: 'AccountDetailSection',
  path: `/accounts/:id/profile`, 
},
{
  authed: true,
  component: AccountProfilePage,
  exact: true, 
  getLink: id => `/accounts/${id}/profile`, 
  icon: 'cog',
  label: 'Account',
  name: 'AccountDetailProfile',
  parent: 'AccountDetailSection',
  path: `/accounts/:id/profile`, 
},
{
  authed: true,
  component: AccountDashboardsPage,
  exact: true, 
  getLink: id => `/accounts/${id}/dashboard`, 
  icon: 'cog',
  label: 'Dashboard', 
  name: 'AccountDetailDashboards',
  parent: 'AccountDetailSection',
  path: `/accounts/:id/dashboard`, 
},
]


class PrivateSection extends React.Component<IProps, IState> {
  classes = { // static values
    button:  'App-navigation--listItemButton',
    container: 'App-navigation',
    header: 'App-navigation--header',
    headerLogo: 'App-navigation--headerLogo',
    listContainer: 'App-navigation--list',
    listItem: 'App-navigation--listItem',
    listItemActive: 'App-subnavigation--listItem--active',
    listItemHover: 'App-navigation--listItem--hover',
    positionBottom: 'App-navigation--bottom',
    positionTop: 'App-navigation--top',
  }
  sharedProps = { // static values
    activeClass: this.classes.listItemActive,
    buttonClass:  this.classes.button,
    buttonContainer: this.classes.listItem,
    hoverClass: this.classes.listItemHover,
    menuContainer: this.classes.listContainer,
    onHover: this.handleMouseIn.bind(this),
  }

  constructor(props: IProps) {
    super(props) 

    this.state = {
      hovering: '',
    }
  }

  handleMouseIn(name: string) {
    this.setState({hovering: name})
  }
  handleMouseOut() {
    this.setState({hovering: ''})
  }

  renderSubNav() {
    const navOpts = {
      hovering: this.state && this.state.hovering || '',      
      onHover: this.handleMouseIn.bind(this),
    }

    const navItems: any = this.props.pages.map(p => { // tslint:disable-line no-any
      const o = {...p}

      if (typeof(o.getLink) === 'function') {
        const {id} = this.props.match && this.props.match.params || {id: ''}

        o.link = o.getLink(id)
        o.getLink = undefined
      }

      o.authed = undefined
      o.exact = undefined
      o.component = undefined

      return {...navOpts, ...o}
    })

    const submenuClasses = {
      active: this.sharedProps.activeClass,
      button:  this.sharedProps.buttonClass,
      buttonContainer: this.sharedProps.buttonContainer,
      hover: this.sharedProps.hoverClass,
      menuContainer: this.sharedProps.menuContainer,
    }

    return (
      <div
        className='profile_subnav'
        style={{height: '100%'}}
        onMouseLeave={() => this.handleMouseOut()}
      >
        <Menu
          items={navItems}
          classes={submenuClasses}
        />
      </div>
    )
  }
  renderContent() {
    return (
      <div className='profile_content'>
        {this.props.pages.map((opts, index) => {
          const o: any = {...opts} // tslint:disable-line no-any
          if (typeof(o.getLink) === 'function') {
            const {id} = this.props.match && this.props.match.params || {id: ''}

            o.link = o.getLink(id)
            o.getLink = undefined
          }

          return (
            <PrivateRoute key={index} {...o}/>
          )
        })}
      </div>
    )
  }
  render() {
    return (
      <div
        className='page--content_container'
      >
        {this.renderSubNav()}
        {this.renderContent()}
      </div>
    )
  }
}

export default PrivateSection

<Button />渲染方法(由<Menu />包裝

 render() {
    const {
      activeClass,
      containerClass,
      exactLink,
      hoverClass,
      icon,
      label,
      link,
      onClick,
      handleActive,
    } = this.props

    let message = (
      <div className='Button--message'>
        <div className='Button--messageText'>{label}</div>
      </div>
    )   
    if (icon) {
      message = (
        <div className='Button--message'>
          <div className='Button--messageIcon'><Icon name={icon} / ></div>
          <div className='Button--messageText'>{label}</div>
        </div>
      )    
    }

    const buttonContainerClass = this.isHovering() ? `${containerClass} ${hoverClass}` : containerClass

    const ButtonContainer = props => (
      <button
        {...props}
        className={this.props.buttonClass || ''}
        onMouseEnter={() => this.handleMouseIn()}
        onMouseLeave={() => this.handleMouseOut()}
      >
        {message}
      </button> 
    )

    let Result
    if (typeof(link) === 'string') {
      if (typeof(activeClass) === 'string' && activeClass.length > 0) {
        const opts = {
          activeClassName: activeClass || '',
          className: buttonContainerClass || '',
          exact: exactLink || false,
          isActive: handleActive || undefined,
          strict: true,
          to: link,
        }

        Result = (
          <NavLink {...opts} >
            <ButtonContainer />
          </NavLink>
        )
      } else {
        Result = (
          <Link to={link} className={buttonContainerClass}>
            <ButtonContainer />
          </Link>
        )
      }

    } else if (typeof(onClick) === 'function') {
      Result = (
        <div className={buttonContainerClass}>
          <ButtonContainer onClick={() => onClick()} />
        </div>
      )

    } else {
      console.warn('Button must have an action props> ', {props: this.props})
    }

    return Result
  }

我遇到了類似的問題,即Switch找不到與其他組件一起包裹的路線。 從源頭看, Switch似乎沒有在子級中遞歸地查找Route ,因此它們不能嵌套。

在這種情況下,要使用Switch您需要重構以使Route成為每個路由的頂級組件。 或重構為不使用Switch基本上使所有路由exact匹配。

切換源: https : //github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Switch.js它使用React.Children.forEach查找路徑,該路徑僅在立即數上進行迭代孩子,而不是嵌套孩子。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM