Saya pada dasarnya mencoba membuat tab bereaksi, tetapi dengan beberapa masalah.
Ini file page.jsx
<RadioGroup>
<Button title="A" />
<Button title="B" />
</RadioGroup>
Ketika Anda mengklik tombol A, kebutuhan komponen RadioGroup ke tombol B de-pilih .
"Dipilih" berarti nama kelas dari negara bagian atau properti
Berikut ini RadioGroup.jsx
:
module.exports = React.createClass({
onChange: function( e ) {
// How to modify children properties here???
},
render: function() {
return (<div onChange={this.onChange}>
{this.props.children}
</div>);
}
});
Sumber dari Button.jsx
tidak terlalu penting, ia memiliki tombol radio HTML biasa yang memicu onChange
kejadian DOM asli
Aliran yang diharapkan adalah:
- Klik pada Tombol "A"
- Tombol "A" memicu onChange, peristiwa DOM asli, yang melembung ke RadioGroup
- Pendengar onChange RadioGroup dipanggil
- RadioGroup perlu de-pilih tombol B . Ini pertanyaan saya.
Inilah masalah utama saya hadapi: Saya tidak bisa bergerak <Button>
s keRadioGroup
, karena struktur ini adalah sedemikian rupa sehingga anak-anak yang sewenang-wenang . Artinya, markup bisa jadi
<RadioGroup>
<Button title="A" />
<Button title="B" />
</RadioGroup>
atau
<RadioGroup>
<OtherThing title="A" />
<OtherThing title="B" />
</RadioGroup>
Saya sudah mencoba beberapa hal.
Percobaan: Dalam RadioGroup
penangan onChange:
React.Children.forEach( this.props.children, function( child ) {
// Set the selected state of each child to be if the underlying <input>
// value matches the child's value
child.setState({ selected: child.props.value === e.target.value });
});
Masalah:
Invalid access to component property "setState" on exports at the top
level. See react-warning-descriptors . Use a static method
instead: <exports />.type.setState(...)
Percobaan: Dalam RadioGroup
penangan onChange:
React.Children.forEach( this.props.children, function( child ) {
child.props.selected = child.props.value === e.target.value;
});
Masalah: Tidak ada yang terjadi, bahkan saya memberikan metode kepada Button
kelascomponentWillReceiveProps
Percobaan: Saya mencoba meneruskan beberapa keadaan tertentu dari orang tua ke anak-anak, jadi saya bisa memperbarui keadaan induk dan meminta anak-anak merespons secara otomatis. Dalam fungsi render RadioGroup:
React.Children.forEach( this.props.children, function( item ) {
this.transferPropsTo( item );
}, this);
Masalah:
Failed to make request: Error: Invariant Violation: exports: You can't call
transferPropsTo() on a component that you don't own, exports. This usually
means you are calling transferPropsTo() on a component passed in as props
or children.
Solusi buruk # 1 : Gunakan metode react-addons.js cloneWithProps untuk mengkloning anak-anak pada waktu render RadioGroup
agar dapat meneruskan properti kepada mereka
Solusi buruk # 2 : Terapkan abstraksi di sekitar HTML / JSX sehingga saya dapat meneruskan properti secara dinamis (bunuh saya):
<RadioGroup items=[
{ type: Button, title: 'A' },
{ type: Button, title: 'B' }
]; />
Dan kemudian RadioGroup
secara dinamis membangun tombol-tombol ini.
Pertanyaan ini tidak membantu saya karena saya perlu membuat anak-anak saya tanpa mengetahui apa mereka
RadioGroup
mungkin yang tahu itu perlu bereaksi terhadap peristiwa anak-anaknya yang sewenang-wenang? Ia harus mengetahui sesuatu tentang anak-anaknya.React.addons.cloneWithProps
dan berikan props baru yang Anda inginkan.props
tidak dapat diubah, jadi Anda membuat hash baru, menggabungkannya dengan props saat ini, dan meneruskan hash baru tersebut sebagaiprops
instance baru dari komponen anak.Jawaban:
Saya tidak yakin mengapa Anda mengatakan bahwa menggunakan
cloneWithProps
adalah solusi yang buruk, tetapi berikut adalah contoh cara menggunakannya.var Hello = React.createClass({ render: function() { return <div>Hello {this.props.name}</div>; } }); var App = React.createClass({ render: function() { return ( <Group ref="buttonGroup"> <Button key={1} name="Component A"/> <Button key={2} name="Component B"/> <Button key={3} name="Component C"/> </Group> ); } }); var Group = React.createClass({ getInitialState: function() { return { selectedItem: null }; }, selectItem: function(item) { this.setState({ selectedItem: item }); }, render: function() { var selectedKey = (this.state.selectedItem && this.state.selectedItem.props.key) || null; var children = this.props.children.map(function(item, i) { var isSelected = item.props.key === selectedKey; return React.addons.cloneWithProps(item, { isSelected: isSelected, selectItem: this.selectItem, key: item.props.key }); }, this); return ( <div> <strong>Selected:</strong> {this.state.selectedItem ? this.state.selectedItem.props.name : 'None'} <hr/> {children} </div> ); } }); var Button = React.createClass({ handleClick: function() { this.props.selectItem(this); }, render: function() { var selected = this.props.isSelected; return ( <div onClick={this.handleClick} className={selected ? "selected" : ""} > {this.props.name} ({this.props.key}) {selected ? "<---" : ""} </div> ); } }); React.renderComponent(<App />, document.body);
Ini jsFiddle yang menunjukkan aksinya.
EDIT : inilah contoh yang lebih lengkap dengan konten tab dinamis: jsFiddle
sumber
this
. Apakah ada keuntungan nyata selain menggunakan React?Tombol harus tanpa kewarganegaraan. Alih-alih memperbarui properti tombol secara eksplisit, cukup perbarui status Grup dan render ulang. Metode render Grup kemudian harus melihat statusnya saat merender tombol dan meneruskan "aktif" (atau sesuatu) hanya ke tombol aktif.
sumber
Mungkin solusi saya adalah solusi yang aneh, tetapi mengapa tidak menggunakan pola pengamat?
module.exports = React.createClass({ buttonSetters: [], regSetter: function(v){ buttonSetters.push(v); }, handleChange: function(e) { // ... var name = e.target.name; //or name this.buttonSetters.forEach(function(v){ if(v.name != name) v.setState(false); }); }, render: function() { return ( <div> <Button title="A" regSetter={this.regSetter} onChange={handleChange}/> <Button title="B" regSetter={this.regSetter} onChange={handleChange} /> </div> ); });
module.exports = React.createClass({ onChange: function( e ) { // How to modify children properties here??? }, componentDidMount: function() { this.props.regSetter({name:this.props.title,setState:this.setState}); }, onChange:function() { this.props.onChange(); }, render: function() { return (<div onChange={this.onChange}> <input element .../> </div>); } });
mungkin Anda memerlukan sesuatu yang lain, tapi menurut saya ini sangat kuat,
Saya lebih suka menggunakan model luar yang menyediakan metode register pengamat untuk berbagai tugas
sumber
Button.jsx
?onChange()
danonChange(e)
Buat objek yang bertindak sebagai perantara antara orang tua dan anak. Objek ini berisi referensi fungsi baik di induk maupun anak. Objek tersebut kemudian diteruskan sebagai prop dari induk ke anaknya. Contoh kode di sini:
https://stackoverflow.com/a/61674406/753632
sumber