Я пытаюсь использовать боковой элемент меню AntD в качестве панели вкладок.
Я хочу разместить компоненты внутри содержимого, чтобы панель содержимого отображала связанный компонент при нажатии элемента меню.
Как мне заставить эту структуру принимать компоненты в качестве содержимого для каждого элемента меню?
import React from 'react';
import { compose } from 'recompose';
import { Divider, Layout, Card, Tabs, Typography, Menu, Breadcrumb, Icon } from 'antd';
import { PasswordForgetForm } from '../Auth/Password/Forgot';
const { Title } = Typography
const { TabPane } = Tabs;
const { Header, Content, Footer, Sider } = Layout;
const { SubMenu } = Menu;
class Dashboard extends React.Component {
state = {
collapsed: false,
};
onCollapse = collapsed => {
console.log(collapsed);
this.setState({ collapsed });
};
render() {
return (
<Layout style={{ minHeight: '100vh' }}>
<Sider collapsible collapsed={this.state.collapsed} onCollapse={this.onCollapse}>
<div />
<Menu theme="light" defaultSelectedKeys={['1']} mode="inline" >
<Menu.Item key="1">
<Icon type="fire" />
<span>Next item</span>
<PasswordForgetForm />
</Menu.Item>
<Menu.Item key="2">
<Icon type="fire" />
<span>Next item</span>
<Another component to render in the content div />
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: 0 }} />
<Content style={{ margin: '0 16px', background: '#fff' }}>
<div style={{ padding: 24, background: '#fff', minHeight: 360 }}>
RENDER RELEVANT COMPONENT HERE BASED ON MENU ITEM SELECTED
</div>
</Content>
</Layout>
</Layout>
);
}
}
export default Dashboard;
Когда я пытаюсь отобразить это, не выдается никаких ошибок, но div содержимого не обновляется с помощью PasswordForgetForm, который я указал в качестве содержимого для пункта меню.
Я попробовал предложение Криса ниже - которое прекрасно работает для рендеринга компонента для каждого из различных элементов div содержимого элемента меню в сегменте макета, однако - недостатком этот подход заключается в том, что при каждой ссылке на страницу sh путь идет к компоненту контента для этого конкретного пункта меню, а не к тестовой странице, на которой есть меню, - и к компоненту контента с соответствующим контентом. Если этот подход одобрен как разумный, есть ли способ сохранить страницу refre sh на исходной странице, вместо попытки go перейти к URL-адресу пункта поднабора?
Обновить
Я нашел эту литературу . Я думаю, что это может быть то, что мне нужно знать, но язык слишком технический, чтобы я мог понять. Кто-нибудь может помочь с простой английской sh версией этого предмета?
Я также нашел этот урок , который использует Pose, чтобы помочь с рендерингом. Хотя эта структура - то, чего я пытаюсь достичь, похоже, что Поза устарела. Кто-нибудь знает, нужно ли go за пределами реагирующего маршрутизатора, чтобы получить такой результат, или есть решение в рамках реагирования, которое я могу реализовать?
Этот пример похож на что я хочу, но я не могу найти ничего, что определяет боковую панель (который, кажется, является аргументом, необходимым для этой работы).
Я также видел этот пост . Хотя некоторые ответы являются копиями и вставками документов, мне интересно, ближе ли ответ Адама Геринга к тому, что мне нужно. Я пытаюсь держать меню Sider на маршруте / da sh постоянно. Этот URL-адрес не должен изменяться - независимо от того, какой элемент меню на стороне пользователя щелкает пользователем, НО содержимое div в компоненте / da sh должно быть обновлено, чтобы отобразить компонент по указанному мною пути маршрута.
ПРИМЕНЕНИЕ ПРЕДЛОЖЕНИЯ КРИСА
Крис любезно предложил следующее предложение. Я попробовал это сделать, но обстоятельства, при которых он не работает должным образом, - это когда щелкают по пункту меню (и соответствующий компонент правильно загружается в div содержимого, но если я обновлю sh страницу, попытка refre sh попытается загрузить страницу с URL-адресом, предназначенным для компонента, который должен находиться внутри содержимого div на странице панели инструментов.
import React from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Switch,
} from 'react-router-dom';
import * as ROUTES from '../../constants/Routes';
import { compose } from 'recompose';
import { Divider, Layout, Card, Tabs, Typography, Menu, Breadcrumb, Icon } from 'antd';
import { withFirebase } from '../Firebase/Index';
import { AuthUserContext, withAuthorization, withEmailVerification } from '../Session/Index';
// import UserName from '../Users/UserName';
import Account from '../Account/Index';
import Test from '../Test/Index';
const { Title } = Typography
const { TabPane } = Tabs;
const { Header, Content, Footer, Sider } = Layout;
const { SubMenu } = Menu;
class Dashboard extends React.Component {
state = {
collapsed: false,
};
onCollapse = collapsed => {
console.log(collapsed);
this.setState({ collapsed });
};
render() {
const { loading } = this.state;
// const dbUser = this.props.firebase.app.snapshot.data();
// const user = Firebase.auth().currentUser;
return (
<AuthUserContext.Consumer>
{authUser => (
<div>
{authUser.email}
<Router>
<Layout style={{ minHeight: '100vh' }}>
<Sider collapsible collapsed={this.state.collapsed} onCollapse={this.onCollapse}>
<div />
<Menu theme="light" defaultSelectedKeys={['1']} mode="inline" >
<SubMenu
key="sub1"
title={
<span>
<Icon type="user" />
<span>Profile</span>
</span>
}
>
<Menu.Item key="2"><Link to={ROUTES.ACCOUNT}>Account Settings</Link></Menu.Item>
<Menu.Item key="3"><Link to={ROUTES.TEST}>2nd content component</Link></Menu.Item>
</SubMenu>
</Menu>
</Sider>
<Layout>
<Header> </Header>
<Content style={{ margin: '0 16px', background: '#fff' }}>
<div style={{ padding: 24, background: '#fff', minHeight: 360 }}>
<Switch>
<Route path={ROUTES.ACCOUNT}>
<Account />
</Route>
<Route path={ROUTES.TEST}>
< Test />
</Route>
</Switch>
</div>
</Content>
<Footer style={{ textAlign: 'center' }}>
test footer
</Footer>
</Layout>
</Layout>
</Router>
</div>
)}
</AuthUserContext.Consumer>
);
}
}
export default Dashboard;
В моем файле маршрутов у меня есть:
export const ACCOUNT = '/account';
Я также нашел этот учебник - в котором используется тот же подход, который описан выше - и не перенаправляется так же, как мой код на странице refre sh. В учебнике вместо этого используется Route BrowserRouter - но в остальном я не вижу никаких отличий.
СЛЕДУЮЩАЯ ПОПЫТКА
Я видел этот пост (спасибо Мэтту). У меня есть попытался следовать рекомендациям в этом посте.
Я удалил внешнюю обертку Router со страницы Dashboard (вокруг приложения есть Router. js, где и настраивается маршрут к Dashboard).
Тогда в м y Dashboard, я изменил div Content на:
Я добавил:
let match = useRouteMatch();
к методу рендеринга внутри моего компонента Dashboard (как показано здесь ).
Я добавил useRouteMatch к своему оператору импорта отact-router-dom.
Это приводит к ошибке, которая говорит:
Ошибка: недопустимый хук вызов. Хуки могут быть вызваны только внутри тела функционального компонента. Это может произойти по одной из следующих причин: 1. У вас могут быть несовпадающие версии React и средства визуализации (например, React DOM) 2. Возможно, вы нарушаете правила хуков
В приведенной выше ошибке есть еще сообщение, но переполнение стека не позволит мне опубликовать его, потому что у него короткая ссылка
Я не знаю Не знаю, что я сделал не так на этих шагах, но если я закомментирую оператор let, страница загрузится.
Когда я go перехожу на / Dashboard и нажимаю "account", я ожидаю аккаунт Компонент для рендеринга внутри содержимого div у меня есть в макете на странице Dashboard. Вместо этого он перенаправляет непосредственно на страницу в localhost3000 / account (для которой нет ссылки на страницу - это просто компонент для отображения на странице Dashboard).
Так что это хуже, чем проблема, с которой я начал - потому что, по крайней мере, при запуске перенаправление происходило только на странице refre sh. Теперь это происходит немедленно.
Я нашел это репо , в котором есть примеры каждого вида маршрута. Я не вижу, что он делает, а я нет.
Этот пост , похоже, имел ту же проблему, что и я, и решил ее, используя тот же подход, что и я. Это сообщение от 2018 года, поэтому с течением времени этот подход может устареть, но я не вижу никакой разницы между тем, что реализует это решение, и моей первоначальной попыткой.
СЛЕДУЮЩАЯ ПОПЫТКА
Я думал, что нашел подход, который работает в ответе Любомира на этот пост .
У меня есть:
<Menu.Item key="2">
<Link to=
{${this.props.match.url}/account
}> Настройки учетной записи
Затем в div в компоненте da sh, где я хочу отобразить этот компонент У меня есть:
<div>
<Switch>
<Route exact path={`${this.props.match.url}/:account`} component={Account} />
Это работает. На странице refre sh я могу продолжать работать как надо.
ОДНАКО, когда я добавляю второй пункт меню с:
<Menu.Item key="16">
<Link to={`${this.props.match.url}/learn`}>
<Icon type="solution" />
<span>Lern</span>
</Link>
</Menu.Item>
вместо при рендеринге компонента Learning при щелчке по пункту меню для / learn (и изменение URL-адреса для обучения) отображается компонент Account. Если я удаляю отображение учетной записи из оператора switch, то у меня может отображаться правильный компонент Learning.
С этой попыткой у меня есть пункты меню, работающие в соответствии с расширением URL панели мониторинга (ie localhost / dash / account или localhost / dash / learn) только для пункта меню ONE . Если я добавлю второй элемент меню, единственный способ правильно отобразить 2-й компонент - это удалить первый элемент меню. Я использую переключатель с точными путями.
Я хочу, чтобы это решение работало с несколькими пунктами меню.
Я пробовал альтернативный путь для URL (например:
<Link to={`${this.props.match.url}/learn`}>
это то же самое, что и
<Link to={`${this.props.match.path}/learn`}>
Я прочитал объяснение в этом блоге , и хотя я не совсем понимаю эти опции. У меня прочитано это . Предполагается, что оператор match теперь является устаревшим методом рендеринга компонентов (теперь, когда доступны хуки). Я не могу найти никаких учебных материалов, которые показывают, как использовать хуки для достижения ожидаемого результата.