Вот рабочий код:
const AppRouter = () => (
<BrowserRouter>
<div>
<Header />
<Switch>
<Route path = "/" component = {DashboardPage} exact = {true} />
<Route path = "/:id" component = {ViewerPage} /> // <-- Exclude Header component from this page
<Route path = "/create" component = {CreatePage} />
<Route path = "/edit/:id" component = {EditPage} />
<Route path = "/help" component = {HelpPage} />
<Route component = {NotFoundPage} />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
Я не мог понять, как исключить компонент Header со страницы компонента ViewerPage. Есть какой-либо способ сделать это?
@Rayon, как бы это выглядело?
Что-то вроде URL === SOMETHING ? null : <Header />
При каких условиях компонент должен появляться / не появляться?
Исключить только на одном конкретном маршруте? {location.pathname !== '/route-to-exclude-header' && <Header />} Если вы хотите исключить более чем один маршрут, создайте массив путей исключения, а затем {exclusionArray.indexOf(location.pathname) > 0 && <Header/>}. Используйте withRouter HoC, предоставляемый пакетом react-router, для внедрения location в ваш компонент.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


1- что-то вроде, в Header.js
import {withRouter} from 'react-router-dom';
class Header extends Component {
render() {
if (this.props.location.pathname === '/') {
return null
}
return (
// other stuff
);
}
}
export default withRouter(Header);
Обратите внимание, что withRouter может отличаться в зависимости от версии реагирующего маршрутизатора. Но идея та же: проверьте свой путь с помощью пути ViewerPage и не отображайте заголовок, если это путь ...
2- Другой подход - сделать то же самое с 'redux'
поэтому всякий раз, когда ViewerPage загружается, отправляйте действие. В ViewerPage.js
class ViewerPage extends Component {
componentDidMount() {
this.props.updateShouldDisplayHeader(false);
}
componentWillUnmount(){
this.props.updateShouldDisplayHeader(true);
}
}
В Header.js
class Header extends Component {
render() {
if (!this.props.shouldDisplayHeader) {
return null;
}
return (
// other stuff
);
}
}
Я полагаю, вы уже знаете, как создавать действия и использовать редукторы на redux
Он хочет условно отобразить заголовок. Вы можете сократить это в содержащем компоненте, который будет отображать заголовок.
Компонент высшего порядка withRouter, предоставляемый пакетом react-router, предоставит вам доступ к объекту местоположения. Как только вы это сделаете, вы можете условно отобразить заголовок путем короткого замыкания.
import {withRouter} from 'react-router'
const App = ({location}) => (
<div>
{location.pathname !== '/exclusion-path' && <Header/>}
<Switch>
...
</Switch>
</div>
)
export default withRouter(App)
или исключить по нескольким путям ...
const exclusionArray = [
'/path-one',
'/another-path',
]
const App = ({location}) => (
<div>
{exclusionArray.indexOf(location.pathname) < 0 && <Header/>}
<Switch>
...
</Switch>
</div>
)
Если вы делаете что-то серьезное, я бы порекомендовал использовать контекстный api и сократить значение, предоставленное контекстом. Если это так, и вам нужно какое-то направление, я буду рад вам это объяснить.
P.S. Если вы хотите сделать это с помощью alpha Hooks API, я буду очень взволнован.
Обновлено: для обращения к commont.
Переместите свой маршрутизатор за пределы компонента приложения.
import {BrowserRouter as Router} from 'react-router-dom'
import ReactDOM from 'react-dom'
ReactDOM.render(
<Router>
<App/>
</Router>,
document.getElementById('render-target')
)
Вот что я получаю ... Uncaught Error: You should not use <Route> or withRouter() outside a <Router>
Переместите ваш <Router/> за пределы компонента приложения. Обратитесь к редактированию.
Я пытаюсь использовать контекстный API, имея HeaderConsumer / HeaderProvider с функцией updateHeader для добавления элементов в заголовок, но мне кажется, что я неправильно использую API. Есть предложения @KyleRichardson?
В моем последнем проекте были точно такие же требования, и я решил разделить заголовок на отдельный компонент и использовать фрагменты React. Идиоматический!
import React, { Fragment } from 'react'
// ...
const App = () => (
<div>
<Switch>
<Route path='/no-header-route' component = {NoHeaderComponent} /> // Route without header
<Fragment> // This is the key
<Header/> // Header is in its own component
<Route path='/route-1' component = {Comp1}/> // Route with header
<Route path='/route-2' component = {Comp2}/> // Route with header
</Fragment>
</Switch>
</div>
)
Безусловно, это самое элегантное решение! Именно то, что я искал, молодец!
Точно самый элегантный ответ на сложившуюся проблему. Ваш ответ спас мне весь день. Спасибо
Ваш путь - продолжать рендеринг страницы 404 в каждом компоненте. Есть ли способ предотвратить это?
Если кто-нибудь читает этот комментарий, я хочу добавить сюда еще один пункт, в моем случае он не работал, если я добавлял <Route path = '/ no-header-route' component = {NoHeaderComponent} /> под закрывающим </Fragment>
В вашем файле маршрутизатора вызовите useRouteMatch () перед <Switch>
export Routes = (
{useRouteMatch("/specific-route")?.isExact ? (
<Header />
) : null}
<Switch>
<Route path = "other/path" component = {Other}
...
</Switch>
);
В качестве альтернативы вызовите withRouter (), чтобы получить прямой доступ к match, location и history.
export const AuthenticatedRoutes = withRouter(() => (
{location.pathname !== `/special-url` ? (
<Header />
) : null}
<Route path = "/special-url" component = {Special}
<Route path = "/other" component = {Other}
));
export Routes = (
{useRouteMatch("/specific-route")?.isExact ? (
<Header />
) : null}
<Switch>
<Route component = {AuthenticatedRoutes}
</Switch>
);
Оберните компонент
<Header />каким-нибудь условием ...