Ich versuche, AntD Menüsider wie ein Registerkartenfeld zu verwenden.
Ich möchte Komponenten in den Inhalt einfügen, damit das Inhaltsfenster die zugehörige Komponente rendert, wenn auf ein Menüelement geklickt wird.
Wie kann ich diese Struktur dazu bringen, Komponenten als Inhalt für jeden Menüpunkt zu verwenden?
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;
Wenn ich versuche, dies zu rendern, werden keine Fehler ausgegeben, aber der Inhaltsbereich wird nicht mit dem PasswordForgetForm aktualisiert, das ich als Inhalt für das Menüelement angegeben habe.
Ich habe den folgenden Vorschlag von Chris ausprobiert - der gut funktioniert, um die Komponente für jeden der verschiedenen Menüelement-Inhaltsbereiche im Layoutsegment zu rendern. Der Nachteil dieses Ansatzes ist jedoch, dass bei jeder Seitenaktualisierung der Pfad zur Inhaltskomponente für geht dieser bestimmte Menüpunkt anstelle der Testseite, auf der sich das Menü befindet - und die Inhaltskomponente mit diesem relevanten Inhalt. Wenn dieser Ansatz als sinnvoll eingestuft wird, gibt es eine Möglichkeit, die Seitenaktualisierung auf der Originalseite beizubehalten, anstatt zu versuchen, zu einer URL eines Teilmengenmenüelements zu wechseln?
Aktualisieren
Ich habe diese Literatur gefunden . Ich denke, das ist vielleicht das, was ich wissen muss, aber die Sprache ist zu technisch, als dass ich sie verstehen könnte. Kann jemand mit einer einfachen englischen Version dieses Themas helfen?
Ich habe auch dieses Tutorial gefunden , das Pose verwendet, um beim Rendern zu helfen. Während ich versuche, diese Struktur zu erreichen, sieht es so aus, als wäre Pose veraltet. Weiß jemand, ob es notwendig ist, über den React-Router hinauszugehen, um dieses Ergebnis zu erzielen, oder gibt es eine Lösung in React, die ich implementieren kann?
Dieses Beispiel ähnelt dem, was ich möchte, aber ich kann nichts finden, das die Seitenleiste definiert (was ein Argument zu sein scheint, das notwendig ist, damit dies funktioniert).
Ich habe diesen Beitrag auch gesehen . Während einige der Antworten ein Kopieren und Einfügen der Dokumente sind, frage ich mich, ob die Antwort von Adam Gering näher an dem liegt, was ich brauche. Ich versuche, das Sider-Menü immer auf der / dash-Route zu halten. Diese URL sollte sich nicht ändern - unabhängig davon, auf welchen Menüpunkt im Sider der Benutzer klickt, ABER der Inhaltsbereich in der Komponente / dash sollte aktualisiert werden, um die Komponente auf dem von mir angegebenen Routenpfad zu rendern.
CHRIS 'VORSCHLAG ANWENDEN
Chris hat freundlicherweise einen Vorschlag unten angeboten. Ich habe es versucht, aber der Umstand, dass es nicht wie gewünscht funktioniert, ist, wenn auf das Menüelement geklickt wird (und die entsprechende Komponente korrekt in den Inhaltsbereich geladen wird, aber wenn ich die Seite aktualisiere, versucht die Aktualisierung, eine Seite mit einem zu laden URL für die Komponente, die sich innerhalb des Inhaltsbereichs auf der Dashboard-Seite befinden soll.
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;
In meiner Routendatei habe ich:
export const ACCOUNT = '/account';
Ich habe auch dieses Tutorial gefunden, das denselben oben beschriebenen Ansatz verwendet und nicht auf die gleiche Weise umgeleitet wird, wie mein Code bei der Seitenaktualisierung. Das Tutorial verwendet Route anstelle von BrowserRouter - ansonsten sehe ich keine Unterschiede.
NÄCHSTER VERSUCH
Ich habe diesen Beitrag gesehen (danke Matt). Ich habe versucht, den Vorschlägen in diesem Beitrag zu folgen.
Ich habe den äußeren Router-Wrapper von der Dashboard-Seite entfernt (um App.js herum befindet sich ein Router, auf dem die Route zum Dashboard eingerichtet wird).
Dann habe ich in meinem Dashboard den Inhaltsbereich geändert in:
Ich fügte hinzu:
let match = useRouteMatch();
auf die Rendermethode in meiner Dashboard-Komponente (wie hier gezeigt ).
Ich habe meiner Importanweisung von react-router-dom useRouteMatch hinzugefügt.
Dies erzeugt einen Fehler, der besagt:
Fehler: Ungültiger Hook-Aufruf. Hooks können nur innerhalb des Körpers einer Funktionskomponente aufgerufen werden. Dies kann aus einem der folgenden Gründe geschehen: 1. Möglicherweise stimmen Versionen von React und des Renderers nicht überein (z. B. React DOM). 2. Möglicherweise verstoßen Sie gegen die Hook-Regeln
Der obige Fehler enthält weitere Meldungen, aber beim Stapelüberlauf kann ich ihn nicht veröffentlichen, da er einen kurzen Link enthält
Ich weiß nicht, was ich in diesen Schritten falsch gemacht habe, aber wenn ich die let-Anweisung auskommentiere, wird die Seite geladen.
Wenn ich zu / Dashboard gehe und auf "Konto" klicke, erwarte ich, dass die Kontokomponente innerhalb des Inhaltsbereichs gerendert wird, den ich im Layout auf der Dashboard-Seite habe. Stattdessen wird direkt zu einer Seite unter localhost3000 / account umgeleitet (für die es keinen Seitenverweis gibt - es ist nur eine Komponente, die innerhalb der Dashboard-Seite gerendert werden muss).
Das ist also schlimmer als das Problem, mit dem ich angefangen habe - denn zumindest zu Beginn erfolgte die Umleitung nur bei der Seitenaktualisierung. Jetzt passiert es sofort.
Ich habe dieses Repo gefunden , das Beispiele für jede Art von Route enthält. Ich kann nicht sehen, was es tut, was ich nicht bin.
Dieser Beitrag scheint das gleiche Problem wie ich gehabt zu haben und hat es mit dem gleichen Ansatz gelöst, den ich versucht habe. Es ist ein Beitrag aus dem Jahr 2018, daher ist der Ansatz im Laufe der Zeit möglicherweise veraltet - aber ich kann keinen Unterschied zwischen der Implementierung dieser Beitragslösung und meinem ursprünglichen Versuch feststellen.
NÄCHSTER VERSUCH
Ich hatte gedacht, ich hätte einen Ansatz gefunden, der in Lyubomirs Antwort auf diesen Beitrag funktioniert .
Ich habe:
<Menu.Item key="2">
<Link to=
{ ${this.props.match.url}/account
}> Kontoeinstellungen
Dann in der div auf der Dash-Komponente, wo ich diese Komponente anzeigen möchte, habe ich:
<div>
<Switch>
<Route exact path={`${this.props.match.url}/:account`} component={Account} />
Das funktioniert. Beim Aktualisieren der Seite kann ich dafür sorgen, dass die Dinge so funktionieren, wie sie sollten.
JEDOCH, wenn ich einen zweiten Menüpunkt hinzufüge mit:
<Menu.Item key="16">
<Link to={`${this.props.match.url}/learn`}>
<Icon type="solution" />
<span>Lern</span>
</Link>
</Menu.Item>
Anstatt die Lernkomponente zu rendern, wenn auf den Menüpunkt für / learn geklickt wird (und die URL-Leiste zum Lernen geändert wird), wird die Kontokomponente gerendert. Wenn ich die Kontoanzeige aus der switch-Anweisung lösche, kann ich die richtige Lernkomponente anzeigen lassen.
Bei diesem Versuch funktionieren die Menüelemente nur für EIN Menüelement mit einer Dashboard-URL-Erweiterung (dh localhost / dash / account oder localhost / dash / learn) . Wenn ich einen zweiten Menüpunkt hinzufüge, kann ich die zweite Komponente nur korrekt rendern, indem ich den ersten Menüpunkt lösche. Ich benutze Schalter mit genauen Pfaden.
Ich möchte, dass diese Lösung mit mehreren Menüelementen funktioniert.
Ich habe versucht, den Pfad für die URL zu wechseln (z. B.:
<Link to={`${this.props.match.url}/learn`}>
ist das gleiche wie:
<Link to={`${this.props.match.path}/learn`}>
Ich habe die Erklärung in diesem Blog gelesen und verstehe diese Optionen zwar nicht ganz. Ich habe diese Zeilen lesen . Es wird vorgeschlagen, dass die Match-Anweisung jetzt eine Legacy-Methode zum Rendern von Komponenten ist (jetzt, da Hooks verfügbar sind). Ich kann keine Schulungsunterlagen finden, die zeigen, wie man mit Haken das erwartete Ergebnis erzielt.
PasswordForgottenForm
Komponente an.Antworten:
Die bessere Lösung besteht darin, mit React Router
<Link>
jedes Menüelement mit einem bestimmten Pfad zu verknüpfen und dann im Inhalt<Switch>
die entsprechende Komponente zu rendern. Hier ist das Dokument: React RouterMit React Router rendern
Mit Menütasten rendern
App.js.
Sider.js
quelle
Ich habe Lyubomirs Antwort auf diesen Beitrag gefunden. Es klappt. Verschachtelte Routen mit React Router v4 / v5
Der Link zum Menüpunkt lautet:
Der Anzeigepfad lautet:
Vor dem Namen der Komponente steht ein Doppelpunkt. Nicht sicher warum. Wenn jemand weiß, wie dieser Ansatz heißt, wäre ich für eine Referenz dankbar, damit ich versuchen kann, ihn zu verstehen.
quelle
:
ist einparams
Platzhalter. So/app/account
ist das gleiche wie/app/sdfsfjfdjfjfdnfjnsdfjn
, was das gleiche ist wie/app/doefmd
und so weiter. Die Zeichenfolge wird lediglich einer deklarierten params-Variablen zugewiesen (siehe Beispiel hier: reacttraining.com/react-router/web/example/url-params , das die Zeichenfolge als params deklariert:id
). Wenn Sie params verwenden möchten, müssen Sie entweder Regex Wegfindung (für Multi params) oder machen Sie Ihre Pfade mehr einzigartig zu verwenden , im/app/dashboard
Vergleich zu/app/settings/5e0b97003e95542de2d8e3a1
, wo5e0b97003e95542de2d8e3a1
ein einzigartiges params istid
./app/:id
würde mit der gleichen Route wie/app/:account
übereinstimmen, die mit der gleichen Route wie übereinstimmen würde/app/settings
. Aufgrund des Param-Platzhalters sind sie nicht eindeutig genug, um mit ihnen übereinzustimmen.