我創建了 Layout 組件,它是由兩個子組件組成的宏頁面布局:BodyContent和RightPanel. 當rightPanelOpenprop 設定為true時,BodyContent占視口寬度的 70%,占寬度RightPanel的 30%。如果rightPanelOpen設定為false ,則BodyContent采用 100% 寬度。我面臨的問題是關于每個子組件如何顯示兒童道具。對于BodyContent,我期待它顯示“這是用于正文內容”,對于RightPanel,我期待看到“右側面板”。但是我看到每個子組件上都顯示了整個句子“這是用于正文內容右側面板”。不知道如何才能從這里進一步剖析兒童道具。我究竟做錯了什么?https://codesandbox.io/s/layout-demo-ts-nsvceu?file=/src/App.tsx:845-906
應用程式.tsx
import "./styles.css";
import React from "react";
import { RightPanel } from "./RightPanel";
import { BodyContent } from "./BodyContent";
export interface LayoutProps {
rightPanelOpen?: boolean;
children?: React.ReactNode;
}
export const Layout: React.FunctionComponent<LayoutProps> & {
RightPanel: typeof RightPanel;
BodyContent: typeof BodyContent;
} = function Layout({ rightPanelOpen = false, children }: LayoutProps) {
const content = rightPanelOpen ? (
<>
<BodyContent sectioned={true}>{children}</BodyContent>
<RightPanel>{children}</RightPanel>
</>
) : (
<BodyContent sectioned={false}>{children}</BodyContent>
);
return <div className="layout-flex">{content}</div>;
};
export default function App() {
return (
<Layout rightPanelOpen={true}>
<Layout.BodyContent sectioned={true}>
<h1> This is for </h1>
<h2> Body content </h2>
</Layout.BodyContent>
<Layout.RightPanel>
<h1>Right Side Panel</h1>
</Layout.RightPanel>
</Layout>
);
}
Layout.RightPanel = RightPanel;
Layout.BodyContent = BodyContent;
正文內容.tsx
import "./styles.css";
export interface BodyContentProps {
children?: React.ReactNode;
sectioned?: boolean;
}
export function BodyContent({ children, sectioned = false }: BodyContentProps) {
return (
<div className={sectioned ? "bodyWidth-70" : "bodyWidth-100"}>
{children}
</div>
);
}
RightPanel.tsx
import "./styles.css";
export interface RightPanelProps {
children?: React.ReactNode;
}
export function RightPanel({ children }: RightPanelProps) {
return <div className="rightSideWidth">{children}</div>;
}
uj5u.com熱心網友回復:
我想出了兩個版本,第一個版本總是同時BodyContent作為RightPanel孩子:
import "./styles.css";
import React, { cloneElement, ReactElement } from "react";
import { RightPanel, RightPanelProps } from "./RightPanel";
import { BodyContent, BodyContentProps } from "./BodyContent";
export interface LayoutProps {
rightPanelOpen?: boolean;
children: [ReactElement<BodyContentProps>, ReactElement<RightPanelProps>];
}
export const Layout: React.FunctionComponent<LayoutProps> & {
RightPanel: typeof RightPanel;
BodyContent: typeof BodyContent;
} = function Layout({
rightPanelOpen = false,
children: [bodyContent, rightPanel]
}: LayoutProps) {
const content = rightPanelOpen ? (
<>
{cloneElement(bodyContent, { sectioned: true })}
{rightPanel}
</>
) : (
<>{bodyContent}</>
);
return <div className="layout-flex">{content}</div>;
};
export default function App() {
return (
<Layout rightPanelOpen={true}>
<Layout.BodyContent>
<h1> This is for </h1>
<h2> Body content </h2>
</Layout.BodyContent>
<Layout.RightPanel>
<h1>Right Side Panel</h1>
</Layout.RightPanel>
</Layout>
);
}
Layout.RightPanel = RightPanel;
Layout.BodyContent = BodyContent;
相反,第二個版本RightPanel僅采用 if rightPanelOpenis true。我不得不放棄函式引數中的道具解構,因為它似乎與有區別的聯合(它應該在較新版本的打字稿中作業正常)混淆:
import "./styles.css";
import React, { cloneElement, ReactElement } from "react";
import { RightPanel, RightPanelProps } from "./RightPanel";
import { BodyContent, BodyContentProps } from "./BodyContent";
export type LayoutProps =
| {
rightPanelOpen?: true;
children: [ReactElement<BodyContentProps>, ReactElement<RightPanelProps>];
}
| {
rightPanelOpen?: false;
children: ReactElement<BodyContentProps>;
};
export const Layout: React.FunctionComponent<LayoutProps> & {
RightPanel: typeof RightPanel;
BodyContent: typeof BodyContent;
} = function Layout(props: LayoutProps) {
let content;
if (props.rightPanelOpen) {
const [bodyContent, rightPanel] = props.children;
content = (
<>
{cloneElement(bodyContent, { sectioned: true })}
{rightPanel}
</>
);
} else {
content = <>{props.children}</>;
}
return <div className="layout-flex">{content}</div>;
};
export default function App() {
return (
<Layout rightPanelOpen={true}>
<Layout.BodyContent>
<h1> This is for </h1>
<h2> Body content </h2>
</Layout.BodyContent>
<Layout.RightPanel>
<h1>Right Side Panel</h1>
</Layout.RightPanel>
</Layout>
);
}
Layout.RightPanel = RightPanel;
Layout.BodyContent = BodyContent;
在這兩個版本中,我都試圖準確地指定組件期望的子級。我還移動了sectioned指定的位置(基于rightPanelOpen)
演示:https ://codesandbox.io/s/layout-demo-ts-forked-2lfyts?file=/src/App.tsx
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/444503.html
標籤:javascript 反应 打字稿
下一篇:使用MUI組件分頁無法按預期作業
