ReactJs菜单链接堆叠主要部分组件

问题描述 投票:0回答:1

我有一个ReactJS Web App使用BrowserRouter和react-router-dom。有一个基本组件,有一个侧栏和一个包含props.children的部分。如果我在地址栏中输入有效路由的网址,它会加载正常,但它必须加载整个应用程序,包括标题和侧边栏。但是,如果我单击侧栏上的链接,它只会加载包含新页面的部分。问题是它还包括新页面下面的上一页。因此,出于某种原因,当按下侧边栏菜单上的链接时,children.props只是将新组件添加到现有的。

继承人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));

最后,这是渲染两个组件的样子:

enter image description here

您可以在我刚刚导航的用户列表组件顶部看到仪表板组件(显示用户角色)。只应显示仪表板组件。现在,如果我直接在地址栏中输入仪表板路线,它会重新加载应用程序并显示我的期望......

enter image description here

javascript reactjs history
1个回答
0
投票

我修好了它。我的app.js在实验中被污染了。恢复原状,现在很好。

© www.soinside.com 2019 - 2024. All rights reserved.