ReactでUIのポップオーバーコンポーネントを作成しています。そのコンポーネントには、ポップオーバーの表示をトリガーするボタンが含まれています。ボタンは構成可能である必要があるため(ラベル、クラス、プロパティ)、これらの構成パラメーターを子に渡す必要があります。私がこれが起こっているのを私が見る主な方法は2つあります。
<PopoverComponent buttonLabel={label} buttonProps={buttonProps} />
const button = <Button>Show</Button>;
<PopoverComponent button={button} />
合併症はポップオーバーの中にある。要素を配置するには、DOMノードにref
が必要なので、PopoverComponent
内のボタン要素に小道具を追加する必要があります。 Reactの場合、これはケース1では簡単で標準です。カスタムの小道具をボタンに広げるだけです。例:<Button ref="popoverButton" onClick={this.onClick} {...extraProps }>
。ただし、ケース2では、React.cloneElement
と小道具を変更します。例えば。、
// INSIDE popoverComponent
const { button } = this.props;
const extendedButton = React.cloneElement(
button,
Object.assign(
{},
button.props, {
ref: "popoverButton",
onClick: this.onClick,
}),
);
return <div className="popover-control">{ extendedButton }</div>;
使用するのはアンチパターンですかReact.cloneElement
およびReactの子コンポーネントの小道具を変更しますか?
アンチパターンかどうかは結論には達していませんが、それぞれのアプローチには賛否両論があります。私の実際の実装では、下流の開発者による使いやすさを向上させるために、両方のインターフェースをサポートしています。開発者は、フルコントロールの実際のReact要素またはデフォルトの動作の小道具を提供できます。
cloneElement
を使用する
長所
短所
通過props
長所
短所
コンポーネントに追加の小道具を追加することが React.cloneElement の目的です。
開始点として
element
を使用して、新しいReact要素を複製して返します。結果の要素には、元の要素の小道具と新しい小道具が浅くマージされます。
通常、これを React.Children API の他のメソッドと組み合わせて使用して、特定の機能を親コンテナーコンポーネントにカプセル化します。たとえば、任意の数のチェックボックスのシーケンス用のチェックされた状態管理コンテナ:
class CheckboxContainer extends React.Component {
constructor (props) {
super();
this.onClick = this.onClick.bind(this);
this.state = {
checked: Array(React.Children.count(props.children)).fill(false)
};
}
onClick (index) {
this.setState({
checked: Object.assign([], this.state.checked, {
index: !this.state.checked[index]
})
});
}
render () {
return React.Children.map(this.props.children, (child, index) => {
return React.cloneElement(child, {
index: index,
onClick: () => this.onClick(index),
checked: this.state.checked[index]
});
});
}
}
class Checkbox extends React.Component {
render () {
return (
<div>
<input type='checkbox'
id={`checkbox-${this.props.index}`}
value={this.props.checked} />
<label for={`checkbox-${this.props.index}`}>
{`Child ${this.props.index}`}
</label>
</div>
);
}
}
class Test extends React.Component {
render () {
return (
<CheckboxContainer>
<Checkbox />
<Checkbox />
<Checkbox />
</CheckboxContainer>
);
}
}
同様のことができます。親のPopoverComponentで開いた状態を管理し、Buttonコンポーネントを子として使用します。ボタンに宣言されているボタンだけに関連するプロップはすべて、親でクローンを作成するときに、ボタンの宣言時にポップオーバー状態の管理に関連するすべてのプロップをマージします。
<PopoverComponent>
<Button label='label' />
</PopoverComponent>
ただし、ポップオーバーは、基になるHTML要素の上にレンダリングされるように見える必要があるため、特別なケースだと思います。これは、明確な親子関係ではありません。 React.cloneElement を使用する場合、key
とref
は他のプロップとは異なる方法で処理されることに注意してください。
元の要素の
key
とref
は保持されます。