私は反応するシンプルなフォームを作成しようとしていますが、データをフォームのdefaultValueに適切にバインドするのが困難に直面しています。
私が探している動作はこれです:
ただし、現在、ページを更新するたびに[テキスト]入力フィールドが空白になっています。 (入力に入力したものは適切に保存され、持続します。)これは、AwayMessageが空のオブジェクトである場合、入力テキストフィールドのhtmlがロードされますが、awayMessageがロードされると更新されないためです。また、フィールドのデフォルト値を指定できません。
わかりやすくするためにコードの一部を削除しました(つまりonToggleChange)
window.Pages ||= {}
Pages.AwayMessages = React.createClass
getInitialState: ->
App.API.fetchAwayMessage (data) =>
@setState awayMessage:data.away_message
{awayMessage: {}}
onTextChange: (event) ->
console.log "VALUE", event.target.value
onSubmit: (e) ->
window.a = @
e.preventDefault()
awayMessage = {}
awayMessage["master_toggle"]=@refs["master_toggle"].getDOMNode().checked
console.log "value of text", @refs["text"].getDOMNode().value
awayMessage["text"]=@refs["text"].getDOMNode().value
@awayMessage(awayMessage)
awayMessage: (awayMessage)->
console.log "I'm saving", awayMessage
App.API.saveAwayMessage awayMessage, (data) =>
if data.status == 'ok'
App.modal.closeModal()
notificationActions.notify("Away Message saved.")
@setState awayMessage:awayMessage
render: ->
console.log "AWAY_MESSAGE", this.state.awayMessage
awayMessageText = if this.state.awayMessage then this.state.awayMessage.text else "Placeholder Text"
`<div className="away-messages">
<div className="header">
<h4>Away Messages</h4>
</div>
<div className="content">
<div className="input-group">
<label for="master_toggle">On?</label>
<input ref="master_toggle" type="checkbox" onChange={this.onToggleChange} defaultChecked={this.state.awayMessage.master_toggle} />
</div>
<div className="input-group">
<label for="text">Text</label>
<input ref="text" onChange={this.onTextChange} defaultValue={awayMessageText} />
</div>
</div>
<div className="footer">
<button className="button2" onClick={this.close}>Close</button>
<button className="button1" onClick={this.onSubmit}>Save</button>
</div>
</div>
awayMessageのconsole.logには以下が表示されます。
AWAY_MESSAGE Object {}
AWAY_MESSAGE Object {id: 1, company_id: 1, text: "Sample Text", master_toggle: false}
入力を初期化する場合はdefaultValueを使用する必要がありますが、状態を使用して値を変更する場合はvalueを使用する必要があります。個人的には、単に初期化する場合はdefaultValueを使用し、送信するときにrefsを使用して値を取得するだけです。反応ドキュメントの参照と入力に関する詳細情報があります https://facebook.github.io/react/docs/forms.html および https://facebook.github.io /react/docs/working-with-the-browser.html 。
入力を書き換える方法は次のとおりです。
awayMessageText = if this.state.awayMessage then this.state.awayMessage.text else ''
<input ref="text" onChange={this.onTextChange} placeholder="Placeholder Text" value={@state.awayMessageText} />
また、実際に値を「プレースホルダーテキスト」に設定するので、プレースホルダーテキストを渡したくありません。未定義で、nilが値を本質的にdefaultValueに変えるため、空白の値を入力に渡す必要があります。 https://facebook.github.io/react/tips/controlled-input-null-value.html 。
GetInitialStateの実行後にAPI呼び出しを行う必要があります。あなたの場合は、componentDidMountで行います。この例に従ってください https://facebook.github.io/react/tips/initial-ajax.html 。
また、reactを使用してコンポーネントのライフサイクルを読むことをお勧めします。 https://facebook.github.io/react/docs/component-specs.html 。
個人的には、レンダリングのロジック以外のすべてを行うのは好きではなく、私の状態で「ロード」を使用し、フォームがロードされる前に素晴らしいスピナーをレンダリングすることを好みます http://fortawesome.github。 io/Font-Awesome/examples / 。ここで私が意味することを示すために書き直します。 cjsxの目盛りを台無しにしたのは、通常、このようなcoffeescriptを使用しているためです。
window.Pages ||= {}
Pages.AwayMessages = React.createClass
getInitialState: ->
{ loading: true, awayMessage: {} }
componentDidMount: ->
App.API.fetchAwayMessage (data) =>
@setState awayMessage:data.away_message, loading: false
onToggleCheckbox: (event)->
@state.awayMessage.master_toggle = event.target.checked
@setState(awayMessage: @state.awayMessage)
onTextChange: (event) ->
@state.awayMessage.text = event.target.value
@setState(awayMessage: @state.awayMessage)
onSubmit: (e) ->
# Not sure what this is for. I'd be careful using globals like this
window.a = @
@submitAwayMessage(@state.awayMessage)
submitAwayMessage: (awayMessage)->
console.log "I'm saving", awayMessage
App.API.saveAwayMessage awayMessage, (data) =>
if data.status == 'ok'
App.modal.closeModal()
notificationActions.notify("Away Message saved.")
@setState awayMessage:awayMessage
render: ->
if this.state.loading
`<i className="fa fa-spinner fa-spin"></i>`
else
`<div className="away-messages">
<div className="header">
<h4>Away Messages</h4>
</div>
<div className="content">
<div className="input-group">
<label for="master_toggle">On?</label>
<input type="checkbox" onChange={this.onToggleCheckbox} checked={this.state.awayMessage.master_toggle} />
</div>
<div className="input-group">
<label for="text">Text</label>
<input ref="text" onChange={this.onTextChange} value={this.state.awayMessage.text} />
</div>
</div>
<div className="footer">
<button className="button2" onClick={this.close}>Close</button>
<button className="button1" onClick={this.onSubmit}>Save</button>
</div>
</div>
これでカバーできます。これは、状態と値を使用するフォームについて説明する1つの方法です。値の代わりにdefaultValueを使用してから、refsを使用して送信時に値を取得することもできます。そのルートに行く場合、データを取得し、それを小道具としてフォームに渡すための外部シェルコンポーネント(通常は高次コンポーネントと呼ばれる)を使用することをお勧めします。
全体として、反応ドキュメントを最後まで読み、いくつかのチュートリアルを行うことをお勧めします。そこにはたくさんのブログがあり、 http://www.egghead.io にはいくつかの良いチュートリアルがありました。私のサイトにも何かあります http://www.openmindedinnovations.com 。
これを修正する別の方法は、入力のkey
を変更することです。
<input ref="text" key={this.state.awayMessage ? 'notLoadedYet' : 'loaded'} onChange={this.onTextChange} defaultValue={awayMessageText} />
更新:これは賛成票を得るので、コンテンツの読み込み中にdisabled
またはreadonly
の小道具を適切に用意する必要があると言わなければならないので、UXエクスペリエンスが低下することはありません。
そして、はい、それはおそらくハックですが、それは仕事を終わらせます.. ;-)
最善のソリューションではないかもしれませんが、次のようなコンポーネントを作成して、コードのどこでも再利用できるようにします。デフォルトですでに反応しているといいのですが。
<MagicInput type="text" binding={[this, 'awayMessage.text']} />
コンポーネントは次のようになります。
window.MagicInput = React.createClass
onChange: (e) ->
state = @props.binding[0].state
changeByArray state, @path(), e.target.value
@props.binding[0].setState state
path: ->
@props.binding[1].split('.')
getValue: ->
value = @props.binding[0].state
path = @path()
i = 0
while i < path.length
value = value[path[i]]
i++
value
render: ->
type = if @props.type then @props.type else 'input'
parent_state = @props.binding[0]
`<input
type={type}
onChange={this.onChange}
value={this.getValue()}
/>`
配列による変更は、配列で表されるパスによってハッシュにアクセスする関数です
changeByArray = (hash, array, newValue, idx) ->
idx = if _.isUndefined(idx) then 0 else idx
if idx == array.length - 1
hash[array[idx]] = newValue
else
changeByArray hash[array[idx]], array, newValue, ++idx
初期値を設定する最も信頼できる方法は、render(){}に加えてcomponentDidMount(){}を使用することです。
...
componentDidMount(){
const {nameFirst, nameSecond, checkedStatus} = this.props;
document.querySelector('.nameFirst').value = nameFirst;
document.querySelector('.nameSecond').value = nameSecond;
document.querySelector('.checkedStatus').checked = checkedStatus;
return;
}
...
要素を簡単に破棄して、新しい要素と置き換えるのは簡単です。
<input defaultValue={this.props.name}/>
このような:
if(document.querySelector("#myParentElement")){
ReactDOM.unmountComponentAtNode(document.querySelector("#myParentElement"));
ReactDOM.render(
<MyComponent name={name} />,
document.querySelector("#myParentElement")
);
};
このバージョンのアンマウント方法も使用できます。
ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(this).parentNode);
パラメーター「placeHolder」に値を指定します。例えば :-
<input
type="text"
placeHolder="Search product name."
style={{border:'1px solid #c5c5c5', padding:font*0.005,cursor:'text'}}
value={this.state.productSearchText}
onChange={this.handleChangeProductSearchText}
/>