2016-12-18 1 views
3

私は、次のコードのように、2 <select>持っている:それが最初にレンダリングされると指定した値が空のときに、なぜ反応しますか?<select>オプション

function FirstSelect(props) { 
 
    const list = props.list.map(item => { 
 
    return <option key={item.id} value={item.id}>{item.text}</option> 
 
    }) 
 
    return <select size='8' onChange={props.onChange}>{list}</select> 
 
} 
 

 
function SecondSelect(props) { 
 
    console.log(props.value) 
 
    const list = props.list.map(item => { 
 
    return <option key={item.id} value={item.id}>{item.text}</option> 
 
    }) 
 
    return <select size='8' onChange={props.onChange} value={props.value}>{list}</select> 
 
} 
 

 
class TwoSelect extends React.Component { 
 
    constructor() { 
 
    super() 
 
    this.state = { 
 
     firstList: [ 
 
     {id: 'fitem1', text: 'fvalue1'}, 
 
     {id: 'fitem2', text: 'fvalue2'} 
 
     ], 
 
     secondList: [ 
 
     {id: 'sitem1', text: 'svalue1'}, 
 
     {id: 'sitem2', text: 'svalue2'} 
 
     ], 
 
     selectedValue1: '', 
 
     selectedValue2: '' 
 
    } 
 
    } 
 

 
    render() { 
 
    return <div> 
 
     <FirstSelect list={this.state.firstList} onChange={(e)=>{this.firstListSelectionChanged(e.target.value)}} /> 
 
     <div>selectedValue1: {this.state.selectedValue1}</div> 
 
     <SecondSelect list={this.state.secondList} value={this.state.selectedValue2} onChange={(e)=>{this.secondListSelectionChanged(e.target.value)}} /> 
 
     <div>selectedValue2: {this.state.selectedValue2}</div> 
 
    </div> 
 
    } 
 

 
    firstListSelectionChanged(value) { 
 
    this.setState({ 
 
     selectedValue1: value 
 
    }) 
 
    } 
 

 
    secondListSelectionChanged(value) { 
 
    this.setState({ 
 
     selectedValue2: value 
 
    }) 
 
    } 
 

 
} 
 

 
ReactDOM.render(
 
    <TwoSelect />, 
 
    document.getElementById('root') 
 
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="root"></div>

、何も奇妙ではありません。しかし、最初の<select>の項目を選択すると、Reactは2番目の<select>の最初の項目を強調表示し、onChangeイベントは発生せず、selectedValue2はまだ空の文字列です。したがって、第2の<select>の最初の項目をクリックしても、そのonChangeイベントは発生しません。

2番目の項目は、2番目の項目をクリックしてからクリックすると表示されます。<select>は、属性値が空のときにハイライト表示されません。

は私が

this.state = { 
    selectedValue1: null, 
    selectedValue2: null 
} 

を使用しようと思っていたようにそれは動作しますが、代わりにnullの空の文字列を使用することを推奨し続けて反応します!

私のコードで何が問題になっていますか?

+0

を見つけることができますか? – Scimonster

+0

@Scimonsterコンソールを実行すると、空の文字列か未定義のいずれかが表示されます。未定義のほうが良いオプションのようです。 – Icepickle

答えて

2

あなたの主な問題は、nullであってはならないが、Reactが示唆するように、未定義または空の文字列である必要があります。

理由はnullは受け入れられない値です。属性は文字列値のみを許可し、オブジェクトは許可しないためです。 nullはオブジェクトなので、使用することはお勧めしません。ただし、定義されていないので、未定義は属性を追加しません。

この理由は、sourcecodeにあります。 selectが複数の値でない場合、値が未定義でない場合、最初のオプションはデフォルトでselectedを取得します。値が指定された場合は、コード値がundefinedに設定されているhere

のコメントセクションで見つけることができるように、それはあなたがこのスニペットで見ることができるように、文句はありません反応し、stringableでなければなりません

いくつかの余分な推奨事項については

class CustomList extends React.Component { 
 
\t render() { 
 
    var selectedId = this.props.selectedValue; 
 
    \t return (
 
    \t <select size="8" onChange={this.props.onChange} value={selectedId}> 
 
     \t { this.props.items.map(item => <option key={item.id} value={item.id}>{item.text}</option>) } 
 
     </select> 
 
    ); 
 
    } 
 
} 
 

 
class TwoSelect extends React.Component { 
 
    constructor() { 
 
    super() 
 
    this.state = { 
 
     firstList: [ 
 
     {id: 'fitem1', text: 'fvalue1'}, 
 
     {id: 'fitem2', text: 'fvalue2'} 
 
     ], 
 
     secondList: [ 
 
     {id: 'sitem1', text: 'svalue1'}, 
 
     {id: 'sitem2', text: 'svalue2'} 
 
     ], 
 
     selectedValue1: undefined, 
 
     selectedValue2: undefined 
 
    } 
 
    } 
 

 
    render() { 
 
    return <div> 
 
     <CustomList placeholder="select" items={this.state.firstList} selectedValue={this.state.selectedValue1} onChange={(e)=>{this.selectionChanged('selectedValue1', e.target.value)}} /> 
 
     <div>selectedValue1: {this.state.selectedValue1}</div> 
 
     <CustomList placeholder="" items={this.state.secondList} selectedValue={this.state.selectedValue2} onChange={(e)=>{this.selectionChanged('selectedValue2', e.target.value)}} /> 
 
     <div>selectedValue2: {this.state.selectedValue2}</div> 
 
    </div> 
 
    } 
 

 
    selectionChanged(stateKey, value) { 
 
    this.setState({ 
 
     [stateKey]: value 
 
    }); 
 
    } 
 
} 
 

 

 
ReactDOM.render(
 
    <TwoSelect />, 
 
    document.getElementById('container') 
 
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 

 
<div id="container"> 
 
    <!-- This element's contents will be replaced with your component. --> 
 
</div>

、あなたは正確に同じことを行う、複数のリストコンポーネントを作成する理由理由はありません。そうすれば、この複雑さを本当に必要としない将来、アプリケーションが非常に複雑になります。

コードで何が再利用できるかを確認してから、それらの単一のコンポーネントだけを使用してください。例えば

は、あなたのFirstListSecondListコンポーネントは、例えばCustomListのために簡略化することができ、その後、あなただけのあなたのTwoSelect renderメソッドで二回CustomListを呼び出す必要があります。

class CustomList extends React.Component { 
    render() { 
    var selectedId = this.props.selectedValue; 
    return (
     <select onChange={this.props.onChange} value={selectedId}> 
     { this.props.items.map(item => <option key={item.id} value={item.id}>{item.text}</option>) } 
     </select> 
    ); 
    } 
} 

selectボックス、主にデフォルト値が選択されているを作成、これを回避するために、あなたは余分な空のオプションを追加することを選択することができ、これは、この場合には事前に選択されます。

私は今あなたのTwoSelectコンポーネントをレンダリングしたい場合、私は(;-)と言う3番目のリストは、後で追加される)、将来的に維持するために、アプリケーションが少し容易にするために、次のものを変更することができ

render() { 
    return <div> 
     <CustomList 
     placeholder="select" 
     items={this.state.firstList} 
     selectedValue={this.state.selectedValue1} 
     onChange={(e)=>{this.selectionChanged('selectedValue1', e.target.value)}} /> 
     <div>selectedValue1: {this.state.selectedValue1}</div> 
     <CustomList 
     placeholder="" 
     items={this.state.secondList} 
     selectedValue={this.state.selectedValue2} 
     onChange={(e)=>{this.selectionChanged('selectedValue2', e.target.value)}} /> 
     <div>selectedValue2: {this.state.selectedValue2}</div> 
    </div>; 
    } 
あなたが見ることができるように、私は2つのハンドラの必要性を取り除く

は、今、あなたの選択が変更されたイベントではなく、次のようになります。これは、あなたから見ることができるようにstateKeyが'selectedValue1'のように、文字列値であることを期待する

selectionChanged(stateKey, value) { 
    this.setState({ 
    [stateKey]: value 
    }) 
} 

変化する

上記のハンドラにjsfiddleを使ってデモがNULLの代わりに空の文字列を使用することをお勧めしリアクトんhere

+0

-1これはタイトルの質問には答えません。 *なぜ*未定義、 'ヌル'、空の文字列を使って、それが動作するようにしますか?そして、なぜそれは2番目のレンダリングでうんざりするだけですか? (また、OPに2つの別々のコンポーネントがある理由があるかもしれません。実際のアプリケーションはもっと複雑かもしれませんが、これはちょうどMCVEです) – Scimonster

+0

@Scimonster Point taken、私は 'null'を使用できない理由を追加しました属性値他の余分なポイントはちょうど勧告ですが、これはちょうどMCVEであるということは間違いないかもしれませんが、イベントや一般的なコンポーネントを扱う他の方法を指摘すると役に立つと思っています – Icepickle

+0

私はそれが理由だとは思わない。私は常にオブジェクトを渡します。リアクション・プロップはどんなタイプでも構いません。 – Scimonster

関連する問題