React input defaultValue不会更新状态 [英] React input defaultValue doesn't update with state

查看:215
本文介绍了React input defaultValue不会更新状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用反应来创建一个简单的表单,但是面临着将数据正确绑定到表单的defaultValue的困难。



我的行为寻找是这样的:


  1. 当我打开我的页面时,文本输入字段应该填入我的数据库中AwayMessage的文本。这就是示例文本。

  2. 理想情况下,如果我的数据库中的AwayMessage没有文本,我希望在文本输入字段中具有占位符。

但是,现在,我发现每次刷新页面时,文本输入字段都是空白的。 (尽管我在输入中输入的内容确实保存并保留。)我认为这是因为当AwayMessage是一个空对象时,输入文本字段的html加载,但当awayMessage加载时不会刷新。此外,我无法指定该字段的默认值。



为了清晰起见,我删除了一些代码(即onToggleChange)

  window.Pages || = {} 

Pages.AwayMessages = React.createClass

getInitialState: - >
App.API.fetchAwayMessage(data)=>
@setState awayMessage:data.away_message
{awayMessage:{}}

onTextChange:(event) - >
console.logVALUE,event.target.value

onSubmit:(e) - >
window.a = @
e.preventDefault()
awayMessage = {}
awayMessage [master_toggle] = @ refs [master_toggle]。getDOMNode()。checked
console.logvalue of text,@refs [text]。getDOMNode()。value
awayMessage [text] = @ refs [text]。getDOMNode()。value
@awayMessage(awayMessage)

awayMessage:(awayMessage) - >
console.logI'm saving,awayMessage
App.API.saveAwayMessage awayMessage,(data)=>
if data.status =='ok'
App.modal.closeModal()
notificationActions.notify(Away Message saved。)
@setState awayMessage:awayMessage

渲染: - >
console.logAWAY_MESSAGE,this.state.awayMessage
awayMessageText = if this.state.awayMessage then this.state.awayMessage.text else占位符文本
`< div className = 远的消息 >
< div className =header>
< h4>外出消息< / h4>
< / div>
< div className =content>
< div className =input-group>
< label for =master_toggle> On?< / label>
< input ref =master_toggletype =checkboxonChange = {this.onToggleChange} defaultChecked = {this.state.awayMessage.master_toggle} />
< / div>
< div className =input-group>
< label for =text>文字< / label>
< input ref =textonChange = {this.onTextChange} defaultValue = {awayMessageText} />
< / div>
< / div>
< div className =footer>
< button className =button2onClick = {this.close}>关闭< / button>
< button className =button1onClick = {this.onSubmit}>储存< /按钮>
< / div>
< / div>

我的console.log for AwayMessage显示如下:

  AWAY_MESSAGE对象{} 
AWAY_MESSAGE对象{id:1,company_id:1,text:Sample Text,master_toggle:false}


解决方案

defaultValue仅用于初始加载



如果你想初始化输入,那么你应该使用defaultValue,但是如果你想使用状态来改变这个值,那么你需要使用值。我个人喜欢只使用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 =textonChange = {this.onTextChange} placeholder =占位符文本value={@state.awayMessageText} />

你也不想像你那样传递占位符文本,因为它实际上将值设置为'占位符文本'。您仍然需要将一个空值传入输入,因为undefined和nil本质上将值转换为defaultValue。 https://facebook.github.io/react/tips/controlled -input-null-value.html



getInitialState无法创建api调用



您需要在getInitialState运行后进行api调用。对于你的情况,我会在componentDidMount中做到这一点。按照此示例, https://facebook.github.io/react/tips/initial -ajax.html

我还建议阅读组件生命周期中的反应。 https://facebook.github.io/react/docs/component-specs.html

用修改和加载状态重写



我个人不喜欢做整个if else else渲染器中的逻辑,并且喜欢在我的状态下使用'loading'并且在表单加载之前呈现字体真棒微调器, http://fortawesome.github.io/Font-Awesome/examples/ 。这是一个改写,向你展示我的意思。如果我搞砸了cjsx的滴答声,那是因为我通常只是用这样的coffeescript,。

pre $ window $页面|| = {}

Pages.AwayMessages = React.createClass

getInitialState: - >
{loading:true,awayMessage:{}}

componentDidMount: - >
App.API.fetchAwayMessage(data)=>
@setState awayMessage:data.away_message,加载: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) - >
#不知道这是什么。我会小心使用像这样的全局变量
window.a = @
@submitAwayMessage(@ state.awayMessage)

submitAwayMessage:(awayMessage) - >
console.logI'm saving,awayMessage
App.API.saveAwayMessage awayMessage,(data)=>
if data.status =='ok'
App.modal.closeModal()
notificationActions.notify(Away Message saved。)
@setState awayMessage:awayMessage

渲染: - >
if this.state.loading
`< i className =fa fa-spinner fa-spin>< / i>`
else
`< div类名=远的消息>
< div className =header>
< h4>外出消息< / h4>
< / div>
< div className =content>
< div className =input-group>
< label for =master_toggle> On?< / label>
< input type =checkboxonChange = {this.onToggleCheckbox} checked = {this.state.awayMessage.master_toggle} />
< / div>
< div className =input-group>
< label for =text>文字< / label>
< input ref =textonChange = {this.onTextChange} value = {this.state.awayMessage.text} />
< / div>
< / div>
< div className =footer>
< button className =button2onClick = {this.close}>关闭< / button>
< button className =button1onClick = {this.onSubmit}>储存< /按钮>
< / div>
< / div>

这应该包括它。现在,这是使用状态和价值的形式的一种方式。您也可以使用defaultValue而不是value,然后在提交时使用refs来获取值。如果你走这条路线,我会建议你有一个外壳组件(通常称为高阶组件)来获取数据,然后将它作为道具传递给表单。



<总体而言,我建议您阅读完整的反应文档并做一些教程。有很多博客, http://www.egghead.io 有一些很好的教程。我的网站上也有一些东西, http://www.openmindedinnovations.com


I'm trying to create a simple form with react, but facing difficulty having the data properly bind to the defaultValue of the form.

The behavior I'm looking for is this:

  1. When I open my page, the Text input field should be filled in with the text of my AwayMessage in my database. That is "Sample Text"
  2. Ideally I want to have a placeholder in the Text input field if the AwayMessage in my database has no text.

However, right now, I'm finding that the Text input field is blank every time I refresh the page. (Though what I type into the input does save properly and persist.) I think this is because the input text field's html loads when the AwayMessage is an empty object, but doesn't refresh when the awayMessage loads. Also, I'm unable to specify a default value for the field.

I removed some of the code for clarity (i.e. 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>

my console.log for AwayMessage shows the following:

AWAY_MESSAGE Object {}
AWAY_MESSAGE Object {id: 1, company_id: 1, text: "Sample Text", master_toggle: false}

解决方案

defaultValue is only for the initial load

If you want to initialize the input then you should use defaultValue, but if you want to use state to change the value then you need to use value. Personally I like to just use defaultValue if I'm just initializing it and then just use refs to get the value when I submit. There's more info on refs and inputs on the react docs, https://facebook.github.io/react/docs/forms.html and https://facebook.github.io/react/docs/working-with-the-browser.html.

Here's how I would rewrite your input:

awayMessageText = if this.state.awayMessage then this.state.awayMessage.text else ''
<input ref="text" onChange={this.onTextChange} placeholder="Placeholder Text" value={@state.awayMessageText} />

Also you don't want to pass placeholder text like you did because that will actually set the value to 'placeholder text'. You do still need to pass a blank value into the input because undefined and nil turns value into defaultValue essentially. https://facebook.github.io/react/tips/controlled-input-null-value.html.

getInitialState can't make api calls

You need to make api calls after getInitialState is run. For your case I would do it in componentDidMount. Follow this example, https://facebook.github.io/react/tips/initial-ajax.html.

I'd also recommend reading up on the component lifecycle with react. https://facebook.github.io/react/docs/component-specs.html.

Rewrite with modifications and loading state

Personally I don't like to do the whole if else then logic in the render and prefer to use 'loading' in my state and render a font awesome spinner before the form loads, http://fortawesome.github.io/Font-Awesome/examples/. Here's a rewrite to show you what I mean. If I messed up the ticks for cjsx, it's because I normally just use coffeescript like this, .

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>

That should about cover it. Now that is one way to go about forms which uses state and value. You can also just use defaultValue instead of value and then use refs to get the values when you submit. If you go that route I would recommend you have an outer shell component (usually referred to as high order components) to fetch the data and then pass it to the form as props.

Overall I'd recommend reading the react docs all the way through and do some tutorials. There's lots of blogs out there and http://www.egghead.io had some good tutorials. I have some stuff on my site as well, http://www.openmindedinnovations.com.

这篇关于React input defaultValue不会更新状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆