【问题标题】:Nested routes in React Router v4 not rendering as expectedReact Router v4 中的嵌套路由未按预期呈现
【发布时间】:2019-05-28 16:36:54
【问题描述】:

过去几天我一直在试图让我的嵌套路由工作,我不得不说我完全迷路了。

我正在尝试使用以下功能:

  1. 带有多个链接的侧边栏。其中之一通往 /banking。
  2. /banking 默认在{ CardWrapper } 内呈现组件{ BankingCards }
  3. 当用户点击{ BankingCards } 渲染的4 张卡片之一的<Link> 时,我想渲染同一个{ CardWrapper } 内的嵌套路径。

在下面的代码块中,您会注意到我尝试使用 switch 语句将组件动态分配给 actionComponent。这似乎以多种方式破坏了功能。

是方法不对,还是我遗漏了一些关于 React Router 组件的东西?

// Banking.js

import CardWrapper from '../../Wrappers/CardWrapper/CardWrapper';
import BankingCards from './BankingCards/BankingCards';
import AddBank from './AddBank/AddBank';
import AddDebit from './AddDebit/AddDebit';
import AddCredit from './AddCredit/AddCredit';
import AddDirect from './AddDirect/AddDirect';

class Banking extends Component {
  state = {};

  render() {
    const { match } = this.props;
    console.log(match.params);
    // let actionComponent;
    // switch (match.params.actionType) { 
    //   case 'add-bank':
    //   actionComponent = AddBank;
    //     break;
    //   case 'add-debit':
    //   actionComponent = AddDebit;
    //     break;
    //   case 'add-credit':
    //   actionComponent = AddCredit;
    //     break;
    //   case 'add-direct':
    //   actionComponent = AddDirect;
    //     break;
    //   default:
    //     return null;
    // }
    return (
      <div className={classes.Banking}>
        <h1 className={classes.mainHeader}>Banking</h1>
        <CardWrapper>
          <Switch>
            <Route exact path={`${match.path}`} component={BankingCards} />
            <Route path={`${match.path}/:actionType`} component={actionComponent} /> 
          </Switch>
        </CardWrapper>
      </div>
    )
  }
}

// BankingCards.js

const bankingCards = ({ match }) => {

  return (
    <>
      <Card>
        <h1>Add Bank Account</h1>
        <Link to={`${match.url}/add-bank`}>
          <SVG src={iconPlus} className={classes.iconPlus} />
        </Link>
        <h3>Manage accounts</h3>
      </Card>

      <Card>
        <h1>Add Debit Card</h1>
        <Link to={`${match.url}/add-debit`}>
          <SVG src={iconPlus} className={classes.iconPlus} />
        </Link>
        <h3>Manage debit cards</h3>
      </Card>

      <Card>
        <h1>Add Credit Card</h1>
        <Link to={`${match.url}/add-credit`}>
          <SVG src={iconPlus} className={classes.iconPlus} />
        </Link>
        <h3>Manage credit cards</h3>
      </Card>

      <Card>
        <h1>Add Direct Debit</h1>
        <Link to={`${match.url}/add-direct`}>
          <SVG src={iconPlus} className={classes.iconPlus} />
        </Link>
        <h3>Manage direct debits</h3>
      </Card>
    </>
  ); 
};

【问题讨论】:

  • 打印什么console.log(match.params);
  • 一个空对象。那时我意识到我做的不对。
  • 一个解决方案可能是使用render 属性而不是component,你可以在里面做你的开关盒

标签: reactjs react-router react-router-v4 react-router-dom


【解决方案1】:

更新:在网站上深入挖掘后找到了解决方案

我的代码存在 3 个问题:

  1. 对于动态的Route,我应该使用render 属性而不是component

    <Switch>
      <Route path={`${match.path}/:actionType`} render={props => {
        const actionType = props.match.params.actionType;
        const Component = getActionComponent(actionType);
        if (Component) {
          return <Component {...props} />;
        } else {
          return <Redirect to="/" />
        }
      }} /> 
      <Route path={`${match.path}`} component={BankingCards} />
    </Switch>
    
  2. 另外,动态路由应该在/banking 之前。这是因为Switch 语句只会呈现第一个匹配项。 /banking 已经是部分匹配,所以路由器没有到达像 /banking/add-bank 这样的嵌套路由。

  3. 父路由/bankingexact 属性设置为true。我现在知道,当使用嵌套路由时,父路由不应该启用exact

    class MainArea extends Component {
      state = {};
    
      render() {
        return (
          <div className={classes.MainArea}>
            <Route path="/banking" component={Banking} />
            <Route exact path="/planner" component={Planner} />
            <Route exact path="/notes" component={Notes} />
          </div>
        );
      }
    }
    

【讨论】:

    【解决方案2】:

    您可以使用render function 来修复您的示例。您有一个错误,因为在 Banking 组件中 math.params 没有 actionType 属性。

    function getActionComponent(actionType) {
       switch (actionType) { 
         case 'add-bank':
           return AddBank;
         case 'add-debit':
           return AddDebit;
         case 'add-credit':
             return AddCredit;
         case 'add-direct':
            return AddDirect;
         default:
            return null;
    }
    
    <Route path={`${match.path}/:actionType`} render={props => {
        const actionType = props.match.params.actionType;
        const Component = getActionComponent(actionType);
        if (Component) {
           return <Component {...props}/>;
        } else {
           return <Redirect to="/"/>
        }
    }}/>
    

    【讨论】:

    • 感谢奥利维尔的建议。我试了一下,但它仍然不起作用。我控制台记录了渲染内部的actionTypeComponent,但仍然没有出现。和以前一样,我可以看到它把我带到了 url 中的 /banking/add-bank,但是 &lt;Banking /&gt; 组件根本没有呈现。例如,甚至没有显示 &lt;h1&gt;Banking&lt;/h1&gt; 标题。我至少希望它能够呈现,但不是 &lt;CardWrapper /&gt;
    • 如果Banking没有显示,问题与负责显示Banking组件的路由有关,你能把代码给我们看看吗?
    • 你对这两个建议都是正确的。我现在发布了更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 2022-01-22
    • 2017-08-28
    • 2017-11-11
    • 2019-01-07
    相关资源
    最近更新 更多