Children props として渡した子コンポーネントが何も表示しない場合に、親のコンポーネントを表示しないようにするにはどう書けるのかをまとめました。
Accordion の要素や ul/li タグの表示の切り替え など、いくつかのユースケースが考えられます
コード
-
App
でParentComponent
を呼び出して、Children Props
としてChildComponent
を記載しています。 -
ChildComponent
には描画するかどうかを Props で渡しています。
App.tsx
import ParentComponent from "./ParentComponent";
import ChildComponent from "./ChildComponent";
const App = () => {
return (
<div className="App">
<ParentComponent>
<ChildComponent
componentRenderable={false}
text={"child component1"}
></ChildComponent>
<ChildComponent
componentRenderable={false}
text={"child component2"}
></ChildComponent>
<ChildComponent
componentRenderable={false}
text={"child component3"}
></ChildComponent>
</ParentComponent>
</div>
);
};
export default App;
ParentComponent.tsx
import * as React from "react";
import ReactDOMServer from "react-dom/server";
interface Props {
children: React.ReactElement[];
}
const ParentComponent = (props: Props) => {
const renderableChildren = props.children.filter(
(child: React.ReactElement) =>
ReactDOMServer.renderToString(child) !== ""
);
if (renderableChildren.length === 0) return null;
return (
<div>
<p>Parent Component</p>
<ul>{props.children}</ul>
</div>
);
};
export default ParentComponent;
ChildComponent.tsx
interface Props {
componentRenderable: boolean;
text: string;
}
const ChildComponent = (props: Props) => {
if (!props.componentRenderable) return null;
return <li>{props.text}</li>;
};
export default ChildComponent;
解説
下記は最初書いて、うまく動作しなかったものです。
(うまく動かなかったもの)ParentComponent.tsx
import * as React from "react";
const ParentComponent = (props: Props) => {
if (props.children.length === 0) return null;
return (
<div>
<p>Parent Component</p>
<ul>{props.children}</ul>
</div>
);};
ChildComponent
で描画を制限していますが、component 自体は children として渡ってしまいます。
なのでここでは、渡ってきた子コンポーネントが描画するのかどうかで親コンポーネントの描画を制限する必要があります。
今回は、ReactDOMServer.renderToString という関数を使用しました。
こちらの関数は、React Element を初期状態の HTML へと変換し、String で返します。
描画しない場合は空文字列が返るため、それを利用して、子コンポーネントが描画されるかどうかを判定することができます。
終わりに
codesandbox に今回のソース上げてます。
動作の確認もできるので、気になる方は見てみてください。