我有一个ReactJS Web App使用BrowserRouter和react-router-dom。有一个基本组件,有一个侧栏和一个包含props.children的部分。如果我在地址栏中输入有效路由的网址,它会加载正常,但它必须加载整个应用程序,包括标题和侧边栏。但是,如果我单击侧栏上的链接,它只会加载包含新页面的部分。问题是它还包括新页面下面的上一页。因此,出于某种原因,当按下侧栏菜单上的链接时,children.props只是将新组件添加到现有的。
Heres app.js:
class App extends Component {
constructor(props){
super(props);
this.state = {authenticated: false};
}
componentDidUpdate(prevProps, prevState, prevContext) {
if (this.props.state.sessionState.appUser && !this.state.authenticated) {
this.setState({authenticated: true});
}
}
render() {
// specify base href from env varible 'WP_BASE_HREF'
// use only if application isn't served from the root
// for development it is forced to root only
/* global WP_BASE_HREF */
const basename = process.env.NODE_ENV === 'development' ? '/' : (WP_BASE_HREF || '/');
return (
<BrowserRouter basename={basename}>
<Routes/>
</BrowserRouter>);
}
}
这是Routes.js
import React from 'react';
import { withRouter, Switch, Route, Redirect } from 'react-router-dom';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import Base from './components/Layout/Base';
import BasePage from './components/Layout/BasePage';
// import BaseHorizontal from './components/Layout/BaseHorizontal';
import CompanyList from './components/Company/CompanyList'
import CompanyDetail from './components/Company/CompanyDetail'
import CompanyCreate from './components/Company/CompanyCreate'
import MyAccount from './components/Users/MyAccount'
import UserList from './components/Users/UserList'
import Dashboard from './components/Dashboard/Dashboard';
import ToolList from './components/Tools/ToolList';
import ToolCreate from './components/Tools/ToolCreate';
import Widgets from './components/Widgets/Widgets';
import Buttons from './components/Elements/Buttons';
import Notifications from './components/Elements/Notifications';
import SweetAlert from './components/Elements/SweetAlert';
import BsCarousel from './components/Elements/Carousel';
import Spinner from './components/Elements/Spinner';
import Animation from './components/Elements/Animation';
import DropdownAnimation from './components/Elements/DropdownAnimation';
import Nestable from './components/Elements/Nestable';
import Sortable from './components/Elements/Sortable';
import Cards from './components/Elements/Cards';
import Grid from './components/Elements/Grid';
import GridMasonry from './components/Elements/GridMasonry';
import Typography from './components/Elements/Typography';
import FontIcons from './components/Elements/FontIcons';
import WeatherIcons from './components/Elements/WeatherIcons';
import Colors from './components/Elements/Colors';
import ChartFlot from './components/Charts/ChartFlot';
import ChartRadial from './components/Charts/ChartRadial';
import ChartChartJS from './components/Charts/ChartChartJS';
import ChartMorris from './components/Charts/ChartMorris';
import ChartChartist from './components/Charts/ChartChartist';
import MapsGoogle from './components/Maps/MapsGoogle';
import MapsVector from './components/Maps/MapsVector';
import TableStandard from './components/Tables/TableStandard';
import TableExtended from './components/Tables/TableExtended';
import Datatable from './components/Tables/DatatableView';
import DataGrid from './components/Tables/DataGrid';
import FormStandard from './components/Forms/FormStandard';
import FormExtended from './components/Forms/FormExtended';
import FormValidation from './components/Forms/FormValidation';
import FormWizard from './components/Forms/FormWizard';
import FormUpload from './components/Forms/FormUpload';
import FormCropper from './components/Forms/FormCropper';
import Login from './components/Pages/Login';
import Register from './components/Pages/Register';
import Recover from './components/Pages/Recover';
import Lock from './components/Pages/Lock';
import NotFound from './components/Pages/NotFound';
import Error500 from './components/Pages/Error500';
import Maintenance from './components/Pages/Maintenance';
import Mailbox from './components/Extras/Mailbox';
import Timeline from './components/Extras/Timeline';
import Calendar from './components/Extras/Calendar';
import Invoice from './components/Extras/Invoice';
import Search from './components/Extras/Search';
import Todo from './components/Extras/Todo';
import Profile from './components/Extras/Profile';
import BugTracker from './components/Extras/BugTracker';
import ContactDetails from './components/Extras/ContactDetails';
import Contacts from './components/Extras/Contacts';
import Faq from './components/Extras/Faq';
import FileManager from './components/Extras/FileManager';
import Followers from './components/Extras/Followers';
import HelpCenter from './components/Extras/HelpCenter';
import Plans from './components/Extras/Plans';
import ProjectDetails from './components/Extras/ProjectDetails';
import Projects from './components/Extras/Projects';
import Settings from './components/Extras/Settings';
import SocialBoard from './components/Extras/SocialBoard';
import TeamViewer from './components/Extras/TeamViewer';
import VoteLinks from './components/Extras/VoteLinks';
import EcommerceOrder from './components/Ecommerce/EcommerceOrders';
import EcommerceOrderView from './components/Ecommerce/EcommerceOrderView';
import EcommerceProduct from './components/Ecommerce/EcommerceProducts';
import EcommerceProductView from './components/Ecommerce/EcommerceProductView';
import EcommerceCheckout from './components/Ecommerce/EcommerceCheckout';
import BlogList from './components/Blog/BlogList';
import BlogPost from './components/Blog/BlogPost';
import BlogArticle from './components/Blog/BlogArticles';
import BlogArticleView from './components/Blog/BlogArticleView';
import ForumCategories from './components/Forum/ForumCategories';
import ForumTopic from './components/Forum/ForumTopics';
import ForumDiscussion from './components/Forum/ForumDiscussion';
import q from './components/AdminTools/querytools';
// List of routes that uses the page layout
// listed here to Switch between layouts
// depending on the current pathname
const listofPages = [
'/login',
'/register',
'/recover',
'/lock',
'/notfound',
'/error500',
'/maintenance'
];
const Routes = ({ location }) => {
const currentKey = location.pathname.split('/')[1] || '/';
const timeout = { enter: 500, exit: 500 };
// Animations supported
// 'rag-fadeIn'
// 'rag-fadeInUp'
// 'rag-fadeInDown'
// 'rag-fadeInRight'
// 'rag-fadeInLeft'
// 'rag-fadeInUpBig'
// 'rag-fadeInDownBig'
// 'rag-fadeInRightBig'
// 'rag-fadeInLeftBig'
// 'rag-zoomBackDown'
const animationName = 'rag-fadeIn'
if(listofPages.indexOf(location.pathname) > -1) {
return (
// Page Layout component wrapper
<BasePage>
<Switch location={location}>
<Route path="/login" component={Login}/>
<Route path="/register" component={Register}/>
<Route path="/recover" component={Recover}/>
<Route path="/lock" component={Lock}/>
<Route path="/notfound" component={NotFound}/>
<Route path="/error500" component={Error500}/>
<Route path="/maintenance" component={Maintenance}/>
</Switch>
</BasePage>
)
}
else {
return (
// Layout component wrapper
// Use <BaseHorizontal> to change layout
<Base>
<TransitionGroup>
<CSSTransition key={currentKey} timeout={timeout} classNames={animationName} exit={false}>
<div>
<Switch location={location}>
{/*My Company*/}
<Route path="/companyList" component={CompanyList}/>
<Route path="/companyDetail" component={CompanyDetail}/>
<Route path="/companyCreate" component={CompanyCreate}/>
{/* User */}
<Route path="/users" component={UserList}/>
<Route path="/myAccount" component={MyAccount}/>
{/*Dashboard*/}
<Route path="/dashboard" component={Dashboard}/>
{/* Tools */}
<Route path="/toolList" component={ToolList}/>
<Route path="/toolCreate" component={ToolCreate}/>
{/*Widgets*/}
<Route path="/widgets" component={Widgets}/>
{/*Elements*/}
<Route path="/buttons" component={Buttons}/>
<Route path="/notifications" component={Notifications}/>
<Route path="/sweetalert" component={SweetAlert}/>
<Route path="/carousel" component={BsCarousel}/>
<Route path="/spinners" component={Spinner}/>
<Route path="/animations" component={Animation}/>
<Route path="/dropdown" component={DropdownAnimation}/>
<Route path="/nestable" component={Nestable}/>
<Route path="/sortable" component={Sortable}/>
<Route path="/cards" component={Cards}/>
<Route path="/grid" component={Grid}/>
<Route path="/grid-masonry" component={GridMasonry}/>
<Route path="/typography" component={Typography}/>
<Route path="/icons-font" component={FontIcons}/>
<Route path="/icons-weather" component={WeatherIcons}/>
<Route path="/colors" component={Colors}/>
{/*Forms*/}
<Route path="/form-standard" component={FormStandard}/>
<Route path="/form-extended" component={FormExtended}/>
<Route path="/form-validation" component={FormValidation}/>
<Route path="/form-wizard" component={FormWizard}/>
<Route path="/form-upload" component={FormUpload}/>
<Route path="/form-cropper" component={FormCropper}/>
{/*Charts*/}
<Route path="/chart-flot" component={ChartFlot}/>
<Route path="/chart-radial" component={ChartRadial}/>
<Route path="/chart-chartjs" component={ChartChartJS}/>
<Route path="/chart-morris" component={ChartMorris}/>
<Route path="/chart-chartist" component={ChartChartist}/>
{/*Table*/}
<Route path="/table-standard" component={TableStandard}/>
<Route path="/table-extended" component={TableExtended}/>
<Route path="/table-datatable" component={Datatable}/>
<Route path="/table-datagrid" component={DataGrid}/>
{/*Maps*/}
<Route path="/map-google" component={MapsGoogle}/>
<Route path="/map-vector" component={MapsVector}/>
{/*Extras*/}
<Route path="/mailbox" component={Mailbox}/>
<Route path="/timeline" component={Timeline}/>
<Route path="/calendar" component={Calendar}/>
<Route path="/invoice" component={Invoice}/>
<Route path="/search" component={Search}/>
<Route path="/todo" component={Todo}/>
<Route path="/profile" component={Profile}/>
<Route path="/ecommerce-orders" component={EcommerceOrder}/>
<Route path="/ecommerce-order-view" component={EcommerceOrderView}/>
<Route path="/ecommerce-products" component={EcommerceProduct}/>
<Route path="/ecommerce-product-view" component={EcommerceProductView}/>
<Route path="/ecommerce-checkout" component={EcommerceCheckout}/>
<Route path="/blog-list" component={BlogList}/>
<Route path="/blog-post" component={BlogPost}/>
<Route path="/blog-articles" component={BlogArticle}/>
<Route path="/blog-article-view" component={BlogArticleView}/>
<Route path="/forum-categories" component={ForumCategories}/>
<Route path="/forum-topics" component={ForumTopic}/>
<Route path="/forum-discussion" component={ForumDiscussion}/>
<Route path="/bug-tracker" component={BugTracker}/>
<Route path="/contact-details" component={ContactDetails}/>
<Route path="/contacts" component={Contacts}/>
<Route path="/faq" component={Faq}/>
<Route path="/file-manager" component={FileManager}/>
<Route path="/followers" component={Followers}/>
<Route path="/help-center" component={HelpCenter}/>
<Route path="/plans" component={Plans}/>
<Route path="/project-details" component={ProjectDetails}/>
<Route path="/projects" component={Projects}/>
<Route path="/settings" component={Settings}/>
<Route path="/social-board" component={SocialBoard}/>
<Route path="/team-viewer" component={TeamViewer}/>
<Route path="/vote-links" component={VoteLinks}/>
<Route path="/q" component={q}/>
<Redirect to="/dashboard"/>
</Switch>
</div>
</CSSTransition>
</TransitionGroup>
</Base>
)
}
}
export default withRouter(Routes);
这是base.js
import React from 'react';
import Header from './Header'
import Sidebar from './Sidebar'
import Offsidebar from './Offsidebar'
import Footer from './Footer'
const Base = props => (
<div className="wrapper">
<Header />
<Sidebar />
<Offsidebar />
<section className="section-container">
{ props.children }
</section>
<Footer />
</div>
)
export default Base;
这里是sidebar.js:
import React, { Component } from 'react';
import { translate, Trans } from 'react-i18next';
import { Link, withRouter } from 'react-router-dom';
import { Collapse, Badge } from 'reactstrap';
import SidebarRun from './Sidebar.run';
import SidebarUserBlock from './SidebarUserBlock';
import MenuData from '../../Menu.js';
import {connect} from "react-redux";
import {compose} from "recompose";
/** Component to display headings on sidebar */
const SidebarItemHeader = ({item}) => (
<li className="nav-heading">
<span><Trans i18nKey={item.translate}>{item.heading}</Trans></span>
</li>
)
/** Normal items for the sidebar */
const SidebarItem = ({item, isActive}) => (
<li className={ isActive ? 'active' : '' }>
<Link to={item.path} title={item.name}>
{item.label && <Badge tag="div" className="pull-right" color={item.label.color}>{item.label.value}</Badge>}
{item.icon && <em className={item.icon}></em>}
<span><Trans i18nKey={item.translate}>{item.name}</Trans></span>
</Link>
</li>
)
/** Build a sub menu with items inside and attach collapse behavior */
const SidebarSubItem = ({item, isActive, handler, children, isOpen}) => (
<li className={ isActive ? 'active' : '' }>
<div className="nav-item" onClick={ handler }>
{item.label && <Badge tag="div" className="pull-right" color={item.label.color}>{item.label.value}</Badge>}
{item.icon && <em className={item.icon}></em>}
<span><Trans i18nKey={item.translate}>{item.name}</Trans></span>
</div>
<Collapse isOpen={ isOpen }>
<ul id={item.path} className="sidebar-nav sidebar-subnav">
{ children }
</ul>
</Collapse>
</li>
)
/** Component used to display a header on menu when using collapsed/hover mode */
const SidebarSubHeader = ({item}) => (
<li className="sidebar-subnav-header">{item.name}</li>
)
var Menu = MenuData.NIL;
class Sidebar extends Component {
constructor(props) {
super(props);
this.state = {
collapse: {},
role: 'NIL'
}
var u = this.props.sessionState.appUser;
Menu = MenuData.NIL;
}
componentDidMount() {
if (this.props.sessionState.appUser) {
const u = this.props.sessionState.appUser;
this.setState({
role: u.role
})
Menu = MenuData[u.role];
}
// pass navigator to access router api
SidebarRun(this.navigator.bind(this));
// prepare the flags to handle menu collapsed states
this.buildCollapseList()
}
componentWillReceiveProps(nextProps) {
if (nextProps.sessionState.appUser) {
const u = nextProps.sessionState.appUser;
this.setState ({
role: u.role
});
Menu = MenuData[u.role];
}
}
/** prepare initial state of collapse menus. Doesnt allow same route names */
buildCollapseList = () => {
let collapse = {};
Menu
.filter(({heading}) => !heading)
.forEach(({name, path, submenu}) => {
collapse[name] = this.routeActive(submenu ? submenu.map(({path})=>path) : path)
})
this.setState({collapse});
}
navigator(route) {
this.props.history.push(route);
}
routeActive(paths) {
paths = Array.isArray(paths) ? paths : [paths];
if (paths.indexOf(this.props.location.pathname.replace('/','')) > -1)
return true;
return false;
}
toggleItemCollapse(stateName) {
for (let c in this.state.collapse) {
if (this.state.collapse[c] === true && c !== stateName)
this.setState({
collapse: {
[c]: false
}
});
}
this.setState({
collapse: {
[stateName]: !this.state.collapse[stateName]
}
});
}
getSubRoutes = item => item.submenu.map(({path}) => path)
/** map menu config to string to determine what elemetn to render */
itemType = item => {
if (item.heading) return 'heading';
if (!item.submenu) return 'menu';
if (item.submenu) return 'submenu';
}
render() {
const r = this.state.role;
const Menu = MenuData[r];
return (
<aside className='aside-container'>
{ /* START Sidebar (left) */ }
<div className="aside-inner">
<nav data-sidebar-anyclick-close="" className="sidebar">
{ /* START sidebar nav */ }
<ul className="sidebar-nav">
{ /* START user info */ }
<li className="has-user-block">
<SidebarUserBlock/>
</li>
{ /* END user info */ }
{ /* Iterates over all sidebar items */ }
{
Menu.map((item, i) => {
// heading
if(this.itemType(item) === 'heading')
return (
<SidebarItemHeader item={item} key={i} />
)
else {
if(this.itemType(item) === 'menu')
return (
<SidebarItem isActive={this.routeActive(item.path)} item={item} key={i} />
)
if(this.itemType(item) === 'submenu')
return [
<SidebarSubItem item={item} isOpen={this.state.collapse[item.name]} handler={ this.toggleItemCollapse.bind(this, item.name) } isActive={this.routeActive(this.getSubRoutes(item))} key={i}>
<SidebarSubHeader item={item} key={i}/>
{
item.submenu.map((subitem, i) =>
<SidebarItem key={i} item={subitem} isActive={this.routeActive(subitem.path)} />
)
}
</SidebarSubItem>
]
}
return null; // unrecognized item
})
}
</ul>
{ /* END sidebar nav */ }
</nav>
</div>
{ /* END Sidebar (left) */ }
</aside>
);
}
}
const mapStateToProps = (state) => ({
sessionState: state.sessionState
});
const mapDispatchToProps = (dispatch) => ({
});
const authCondition = (authUser) => !!authUser;
export default compose(
withRouter,
connect(mapStateToProps, mapDispatchToProps),
translate('translations')
)(Sidebar);
//export default translate('translations')(withRouter(Sidebar));
最后,这就是渲染两个组件的原因:
您可以在我刚刚导航的用户列表组件顶部看到仪表板组件(显示用户角色)。只应显示仪表板组件。现在,如果我直接在地址栏中输入仪表板路线,它会重新加载应用程序并显示我的期望...
答案 0 :(得分:0)
我修好了。我的app.js在实验中被污染了。恢复原状,现在很好。