首页 > 解决方案 > 如何在 React 中渲染不同的布局?

问题描述

我正在尝试使用 React 显示不同的布局。我有带有链接的导航栏。对于每个链接(服务、工作、联系人...等)我想呈现导航栏,但对于登录链接我不想显示它。所以我的代码如下:

import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import PublicLayout from './components/layouts/PublicLayout';
import SigninLayout from './components/layouts/SigninLayout';
import Main from './components/pages/Main';
import Services from './components/pages/Services';
import Price from './components/pages/Price';
import Works from './components/pages/Works';
import Signin from './components/pages/Signin';
import NotFound from './components/pages/NotFound';

class App extends Component {
    render() {
        return (
            <BrowserRouter>
                <div className="App">
                    <Switch>
                        <PublicLayout>
                            <Route exact path='/' component={Main} />
                            <Route exact path='/services' component={Services} />
                            <Route exact path='/prices' component={Price} />
                            <Route exact path='/works' component={Works} />
                        </PublicLayout>
                        <SigninLayout>
                            <Route exact path='/signin' component={Signin} />
                        </SigninLayout>
                        <Route path="*" component={NotFound} />
                    </Switch>
                </div>
            </BrowserRouter>
        );
    }
}

export default App;

我希望 SigninLayout 应该用于 SignIn url。但我仍然看到导航栏。这是我的 SigninLayout 代码:

import React, { Component } from 'react';

class SigninLayout extends Component {
    state = {

    }

    render() {
        return (
            <div>
                { this.props.children }
            </div>
        );
    }
}

export default SigninLayout;

这是我的登录组件:

import React, { Component } from 'react';

class Signin extends Component {
    state = {

    }

    render() {
        return (
            <div>
                <h1>Войти</h1>
                <form>
                    <input type="text" placeholder="укажите e-mail" />
                    <input type="text" placeholder="укажите пароль" />
                    <button>Войти</button>
                </form>
            </div>
        );
    }
}

export default Signin;

为什么显示导航栏?我做错了什么?

升级版:

import React, { Component } from 'react';
import Navbar from '../nav/Navbar';

class PublicLayout extends Component {
    state = {
        items: [
            { id: 1, name: 'Услуги', link: '/services' },
            { id: 2, name: 'Цены', link: '/prices' },
            { id: 3, name: 'Как это работает?', link: '/works' },
            { id: 4, name: 'Войти', link: '/signin' },
        ]
    }

    render() {
        return (
            <div>
                <Navbar items={ this.state.items } />
                { this.props.children }
            </div>
        );
    }
}

export default PublicLayout;

标签: javascriptreactjs

解决方案


首先让我们使用<Switch>,如果您已经找到了您的路线,则无需评估任何其他路线:

class App extends Component {
    render() {
        return (
            <BrowserRouter>
                <div className="App">
                    <Switch>
                        <Route exact path='/signin' component={SigninLayout} />
                        <Route component={PublicLayout} />
                    </Switch>
                </div>
            </BrowserRouter>
        );
    }
}

请注意,我们在这里选择两种布局,子路线将去那里。这是您的错误:即使其子组件都不可见(嗯...除非它本身是空的),也会呈现外部组件(PublicLayoutand )。SigningLayout

const PublicLayout = () => (
    <Switch>
        <Route exact path='/' component={Main} />
        <Route exact path='/services' component={Services} />
        <Route exact path='/prices' component={Price} />
        <Route exact path='/works' component={Works} />
    </Switch>
);

并行SigningLayout应该很容易。当然这只是一个例子,但对于(未经测试)来说应该是微不足道的:

const App = () => (
    <BrowserRouter>
        <div className="App">
            <Switch>
                <Route exact path='/signin'>
                    <SigningLayout><SignIn /></SigningLayout>
                </Route>
                <Route>
                    <PublicLayout>
                        <Switch>
                            <Route exact path='/' component={Main} />
                            <Route exact path='/services' component={Services} />
                            <Route exact path='/prices' component={Price} />
                            <Route exact path='/works' component={Works} />
                        </Switch>
                    <PublicLayout>
                </Route>
            </Switch>
        </div>
    </BrowserRouter>
);

推荐阅读