我正在为妻子设计一个预算应用程序,以便我使用和学习反应。我的应用程序具有侧边栏和顶部导航。侧边栏有一个动态生成的帐户列表以及一个主页,其中将显示一些支出报告。选择其中一个帐户会加载一个Transactions
组件,该组件将呈现每个帐户的交易。
单击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和一些共享同一组件的链接的侧边栏。
答案 0 :(得分:1)
对于react路由器,您需要将ID作为URL参数传递到render a dynamic route,在您的情况下,假设accountId
,App.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;
}