我正在尝试使用react创建一个简单的表单,但是在将数据正确绑定到表单的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}
发布于 2017-01-18 19:04:55
解决这个问题的另一种方法是更改输入的key
。
<input ref="text" key={this.state.awayMessage ? 'notLoadedYet' : 'loaded'} onChange={this.onTextChange} defaultValue={awayMessageText} />
更新:由于这一点得到了支持,我不得不说,在加载内容时,你应该适当地使用disabled
或readonly
道具,这样就不会降低用户体验。
是的,这很可能是一种黑客行为,但它可以完成工作。;-)
发布于 2015-05-10 15:48:04
defaultValue仅用于初始加载
如果你想初始化输入,那么你应该使用defaultValue,但是如果你想使用状态来改变值,那么你需要使用value。就我个人而言,如果我只是在初始化defaultValue,那么我喜欢只使用它,然后在提交时只使用ref来获取值。在react文档、https://facebook.github.io/react/docs/forms.html和https://facebook.github.io/react/docs/working-with-the-browser.html上有更多关于ref和input的信息。
下面是我将如何重写您的输入:
awayMessageText = if this.state.awayMessage then this.state.awayMessage.text else ''
<input ref="text" onChange={this.onTextChange} placeholder="Placeholder Text" value={@state.awayMessageText} />
你也不想像你那样传递占位符文本,因为这实际上会将值设置为“占位符文本”。您仍然需要将一个空值传递给输入,因为undefined和nil本质上会将值转换为defaultValue。https://facebook.github.io/react/tips/controlled-input-null-value.html。
getInitialState无法进行api调用
您需要在getInitialState运行后进行接口调用。对于你的情况,我会用componentDidMount来做。遵循下面的示例,https://facebook.github.io/react/tips/initial-ajax.html。
我还建议阅读有关react组件生命周期的内容。https://facebook.github.io/react/docs/component-specs.html。
使用修改和加载状态重写
就我个人而言,我不喜欢在渲染中做整个if else then逻辑,而更喜欢在我的状态下使用'loading‘,并在窗体加载之前渲染一个非常棒的字体旋转器,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>
这应该就够了。这是使用状态和值的表单的一种方式。你也可以只使用defaultValue而不是value,然后在提交时使用refs来获取这些值。如果采用这种方式,我建议您使用一个外壳组件(通常称为高阶组件)来获取数据,然后将其作为props传递给表单。
总的来说,我建议从头到尾阅读react文档,并做一些教程。有很多博客,http://www.egghead.io有一些很好的教程。我的网站上也有一些东西,http://www.openmindedinnovations.com。
发布于 2015-05-10 07:38:27
也许不是最好的解决方案,但我会像下面这样做一个组件,这样我就可以在代码中的任何地方重用它。我希望默认情况下它已经在react中了。
<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()}
/>`
其中,change by array是通过数组表示的路径访问散列的函数
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
https://stackoverflow.com/questions/30146105
复制相似问题