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のコンポーネントをレンダリングするのにうまく機能しますが、このアプローチの欠点は、ページを更新するたびに、パスがメニューがあるテストページではなく、その特定のメニュー項目、およびその関連コンテンツを持つコンテンツコンポーネント。このアプローチが賢明であると承認されている場合、サブセットメニューアイテムのURLに移動するのではなく、元のページでページを更新し続ける方法はありますか?
更新
この文学を見つけた。これは私が知る必要があるかもしれないと思いますが、言語は私には理解するにはあまりにも専門的です。誰でもこの主題の簡単な英語版を手伝ってくれる?
また、ポーズを使用してレンダリングを支援するこのチュートリアルを見つけました。この構造は私が達成しようとしているものですが、ポーズは廃止されているようです。この結果を得るためにreact-routerを超える必要があるかどうか誰かが知っていますか、またはreact内に実装するように見える解決策がありますか?
この例は私が欲しいものに似ていますが、サイドバーを定義するものは何も見つかりません(これは、この機能を動作させるために必要な引数のようです)。
私もこの記事を見ました。回答の一部はドキュメントのコピーと貼り付けですが、Adam Geringの回答が必要なものに近いのではないかと思います。私は常に/ dashルートにSiderメニューを維持しようとしています。そのURLは変更しないでください。ユーザーがサイダーのどのメニュー項目をクリックしたかに関係なく、/ dashコンポーネントのコンテンツdivを更新して、指定したルートパスでコンポーネントをレンダリングする必要があります。
クリスの提案の適用
クリスは以下の提案を親切に提供してくれました。試してみましたが、メニュー項目がクリックされたとき(そして関連するコンポーネントがコンテンツdivに正しくロードされたときに、期待どおりに動作しない状況ですが、ページを更新すると、更新によってページが読み込まれます。ダッシュボードページのコンテンツdiv内にあると想定されるコンポーネントのURL。
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;
私のroutesファイルには、次のものがあります:
export const ACCOUNT = '/account';
私はこのチュートリアルも見つけました-これは上記で概説したのと同じアプローチを使用しており、ページの更新時にコードが行うのと同じ方法でリダイレクトされません。このチュートリアルではBrowserRouterの代わりにRouteを使用していますが、それ以外の点では違いがわかりません。
次の試み
私はこの投稿を見ました(Mattに感謝します)。私はその投稿の提案に従うようにしました。
ダッシュボードページから外部ルーターラッパーを削除しました(ダッシュボードへのルートが設定されているApp.jsの周りにルーターがあります)。
次に、ダッシュボードでコンテンツdivを次のように変更しました。
追加した:
let match = useRouteMatch();
ここに示すように、ダッシュボードコンポーネント内のrenderメソッドに追加します。
react-router-domからのimportステートメントにuseRouteMatchを追加しました。
これにより、次のようなエラーが発生します。
エラー:無効なフック呼び出し。フックは、関数コンポーネントの本体の内部でのみ呼び出すことができます。これは、次のいずれかの理由で発生する可能性があります。1. Reactとレンダラー(React DOMなど)のバージョンが一致していない可能性があります。2.フックのルールに違反している可能性があります。
上記のエラーにはより多くのメッセージがありますが、短いリンクがあるため、スタックオーバーフローでは投稿できません
これらの手順で何が間違っていたかはわかりませんが、letステートメントをコメントアウトすると、ページが読み込まれます。
/ Dashboardに移動して[アカウント]をクリックすると、ダッシュボードページのレイアウトにあるコンテンツdiv内にアカウントコンポーネントが表示されることを期待しています。代わりに、localhost3000 / accountのページに直接リダイレクトします(ページ参照はありません-これは、ダッシュボードページ内にレンダリングするコンポーネントにすぎません)。
ですから、これは私が始めた問題よりも悪いです-少なくとも最初は、リダイレクトはページの更新時にのみ発生したためです。今ではすぐに起こります。
さまざまなルートの例が含まれているこのレポを見つけました。私がしていないことが何をしているのか分かりません。
この投稿は私と同じ問題を抱えていたようで、私が試したのと同じ方法で解決しました。2018年からの投稿なので、時間が経つとアプローチが古くなるかもしれませんが、その投稿ソリューションの実装と私の最初の試みとの違いはわかりません。
次の試み
私はこの投稿に対するリュボミールの答えで機能するアプローチを見つけたと思っていました。
私が持っています:
<Menu.Item key="2">
<Link to=
{ ${this.props.match.url}/account
}>アカウント設定
次に、私が持っているこのコンポーネントを表示したいダッシュコンポーネントのdivで:
<div>
<Switch>
<Route exact path={`${this.props.match.url}/:account`} component={Account} />
これは機能します。ページを更新すると、正常に機能するようになります。
しかし、次のように2番目のメニュー項目を追加すると、
<Menu.Item key="16">
<Link to={`${this.props.match.url}/learn`}>
<Icon type="solution" />
<span>Lern</span>
</Link>
</Menu.Item>
/ learnのメニュー項目をクリックすると(およびURLバーが学習に変化する)、ラーニングコンポーネントがレンダリングされる代わりに、アカウントコンポーネントがレンダリングされます。switchステートメントからアカウントの表示を削除すると、正しい学習コンポーネントを表示できます。
この試みで、私はのために(つまり、ローカルホスト/ダッシュ/アカウントまたはローカルホスト/ダッシュ/学ぶ)ダッシュボードのURLの拡張子に一致するように取り組んでメニュー項目を持っているONEのみのメニュー項目。2番目のメニュー項目を追加した場合、2番目のコンポーネントを正しくレンダリングする唯一の方法は、最初のメニュー項目を削除することです。正確なパスを持つスイッチを使用しています。
このソリューションで複数のメニュー項目を処理したい。
私はURLのパスを変更しようとしました(例:
<Link to={`${this.props.match.url}/learn`}>
と同じです:
<Link to={`${this.props.match.path}/learn`}>
私はこのブログの説明を読みましたが、これらのオプションを完全には理解していません。私はこれを読みました。これは、matchステートメントがコンポーネントをレンダリングするためのレガシーメソッドであることを示しています(フックが利用可能になりました)。期待される結果を達成するためにフックを使用する方法を示すトレーニング資料が見つかりません。
PasswordForgottenForm
コンポーネントも含めてください。