侧边栏中的动态和非动态路线

时间:2019-09-11 17:16:53

标签: reactjs react-router

我正在为妻子设计一个预算应用程序,以便我使用和学习反应。我的应用程序具有侧边栏和顶部导航。侧边栏有一个动态生成的帐户列表以及一个主页,其中将显示一些支出报告。选择其中一个帐户会加载一个Transactions组件,该组件将呈现每个帐户的交易。

enter image description here

单击Home按钮时,应将主窗格中的Transactions组件替换为我的HomePage组件,但我一直无法弄清楚如何制作与react-router一起工作。希望这是有道理的。

这是当前侧边栏的构建方式:

import React from 'react';
import axios from 'axios';

import classnames from 'classnames';

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faMoneyCheck, faCreditCard, faPiggyBank, faHome } from '@fortawesome/free-solid-svg-icons'

const API = 'http://127.0.0.1:8000/api/accounts/';

class AccountNavigation extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      data: [],
      checkingAccounts: [],
      savingsAccounts: [],
      creditCardAccounts: [],
      selectedAccount: null,
    }
  }

  handleAccountSelect = (event) => {
    // console.log(event)
    this.props.handleAccountSelect(event.target.value)
    this.setState({
      selectedAccount: event.target.value
    })
  }

  componentDidMount() {
    this.setState({
      isLoading: true
    }, () => {
      // console.log(this.state);
    });

    axios.get(API).then(response => {
      this.setState({
        data: response.data,
        checkingAccounts: response.data.checking,
        savingsAccounts: response.data.savings,
        creditCardAccounts: response.data.credit_card,
        isLoading: false,
      });
    });
  }

  render() {
    const {
      checkingAccounts,
      savingsAccounts,
      creditCardAccounts
    } = this.state;

    return (
      <nav className="no-col-padding bg-light col-md-2 sidebar d-none d-md-block">
        <div className="sidebar-sticky">
          <h6 className="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1">
            <span><FontAwesomeIcon icon={faHome} /> Home</span>
          </h6>
          <h6 className="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1">
            <span><FontAwesomeIcon icon={faMoneyCheck} /> Checking</span>
          </h6>
          <ul class="nav flex-column">
              { checkingAccounts.map((account) => {
                var btnClass = classnames({
                  btn: true,
                  'btn-link': true,
                  'nav-link': true,
                  'active': this.state.selectedAccount === account.id.toString()
                });

                  return (
                    <li className="nav-item">
                      <button eventKey={account.id} type="button" className={btnClass} onClick={this.handleAccountSelect} value={account.id}>
                        { account.account_name }
                      </button>
                    </li>
                  )
              })}
          </ul>
          <h6 className="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1">
            <span><FontAwesomeIcon icon={faCreditCard} /> Credit Cards</span>
          </h6>
          <ul className="nav flex-column">
              { creditCardAccounts.map((account) => {
                var btnClass = classnames({
                  btn: true,
                  'btn-link': true,
                  'nav-link': true,
                  'active': this.state.selectedAccount === account.id.toString()
                });

                  return (
                    <li className="nav-item" activeClassName="active">
                      <button eventKey={account.id} type="button" className={btnClass} onClick={this.handleAccountSelect} value={account.id}>
                        { account.account_name }
                      </button>
                    </li>
                  )
              })}
          </ul>
          <h6 className="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1">
            <span><FontAwesomeIcon icon={faPiggyBank} /> Savings</span>
          </h6>
          <ul className="nav flex-column">
              { savingsAccounts.map((account) => {
                var btnClass = classnames({
                  btn: true,
                  'btn-link': true,
                  'nav-link': true,
                  'active': this.state.selectedAccount === account.id.toString()
                });

                  return (
                    <li className="nav-item" activeClassName="active">
                      <button eventKey={account.id} type="button" className={btnClass} onClick={this.handleAccountSelect} value={account.id}>
                        { account.account_name }
                      </button>
                    </li>
                  )
              })}
          </ul>
        </div>
      </nav>
    )
  };
}

export default AccountNavigation;

还有我的App.js:

import React from 'react';
import AccountNavigation from './components/AccountNavigation';
import Transactions from './components/Transactions';
import TransactionButtons from './components/TransactionButtons';

import Header from './components/Header';

class App extends React.Component {
  constructor() {
    super();

    this.state = {
      selectedAccount: null,
      showTransactionForm: false
    }

    this.handleAccountSelect = this.handleAccountSelect.bind(this);
  }

  handleAccountSelect = (accountId) => {
    // console.log("print handleAccountSelect called")
    // console.log(accountId)
    this.setState({selectedAccount: accountId});
  };

  render() {
    return (
      <div className="App">
        {/* <Header /> */}
        <nav class="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
          <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="#">Budget Zen</a>
            {/* <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search"> */}
          <ul class="navbar-nav px-3">
            <li class="nav-item text-nowrap">
              <a class="nav-link" href="#">Sign out</a>
            </li>
          </ul>
        </nav>
        <div className="container-fluid">
          <div className="row">
            <AccountNavigation
              handleAccountSelect = {this.handleAccountSelect} />
            <main role="main" className="col-md-9 ml-sm-auto col-lg-10 px-4">
                <div className="col-10">
                  <Transactions
                    selectedAccount = {this.state.selectedAccount}
                    showTransactionForm = {this.state.showTransactionForm}/>
                </div>
            </main>
          </div>
        </div>
      </div>);
  }
}

export default App;

我看过很多示例,但是它们都没有涉及同时使用react-router和一些共享同一组件的链接的侧边栏。

1 个答案:

答案 0 :(得分:1)

对于react路由器,您需要将ID作为URL参数传递到render a dynamic route,在您的情况下,假设accountIdApp.js中的Route配置将是:

import React from 'react';
import { BrowserRouter, Router, Link, Switch } from "react-router-dom";
import AccountNavigation from './components/AccountNavigation';
import Transactions from './components/Transactions';
import TransactionButtons from './components/TransactionButtons';

import Header from './components/Header';

class App extends React.Component {
  constructor() {
    super();

    this.state = {
      showTransactionForm: false
    }

  }

  render() {
    return (
      <BrowserRouter>
        <div className="App">
          <nav class="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
            <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="#">Budget Zen</a>
              {/* <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search"> */}
            <ul class="navbar-nav px-3">
              <li class="nav-item text-nowrap">
                <a class="nav-link" href="#">Sign out</a>
              </li>
            </ul>
          </nav>
          <div className="container-fluid">
            <div className="row">
              <AccountNavigation
                handleAccountSelect = {this.handleAccountSelect} />
              <main role="main" className="col-md-9 ml-sm-auto col-lg-10 px-4">
                  <div className="col-10">
                    <Switch>
                      <Route path="/home" component={Home} />
                      <Route path="/:accountId" render={(props) => (<Transaction showTransactionForm = {this.state.showTransactionForm} {...props}/>)} />
                    </Switch>
                  </div>
              </main>
            </div>
          </div>
        </div>
     </BrowserRouter> 
     );
  }
}

export default App;

AccountNavigation内,您可以通过以下方式进行路由:

  handleAccountSelect = (event) => {
    this.props.history.push(event.target.value);
    this.setState({
      selectedAccount: event.target.value
    })
  }

请记住,AccountNavigation不在Route中,您需要用withRouter包裹它才能收到history道具:

export default withRouter(AccountNavigation);

Transaction组件内部,您可以通过以下方式收到所选的accountId

componentDidMount() {
  const { accountId } = this.props.match.params;
}