簡體   English   中英

反應輸入默認值不隨狀態更新

[英]React input defaultValue doesn't update with state

我正在嘗試使用 react 創建一個簡單的表單,但是在將數據正確綁定到表單的 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.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}

解決此問題的另一種方法是更改​​輸入的key

<input ref="text" key={this.state.awayMessage ? 'notLoadedYet' : 'loaded'} onChange={this.onTextChange} defaultValue={awayMessageText} />

更新:由於這得到了贊成,我不得不說你應該在加載內容時正確地設置一個disabledreadonly道具,這樣你就不會降低用戶體驗。

是的,這很可能是一次黑客攻擊,但它完成了工作.. ;-)

defaultValue 僅用於初始加載

如果要初始化輸入,則應使用 defaultValue,但如果要使用 state 更改值,則需要使用 value。 我個人喜歡只使用 defaultValue 如果我只是初始化它,然后在我提交時使用 refs 來獲取值。 關於反應文檔的參考和輸入的更多信息, https://facebook.github.io/react/docs/forms.htmlhttps://facebook.github.io/react/docs/working-with-the-瀏覽器.html

以下是我將如何重寫您的輸入:

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 本質上將 value 轉換為 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

我還建議閱讀 react 的組件生命周期。 https://facebook.github.io/react/docs/component-specs.html

用修改和加載狀態重寫

就我個人而言,我不喜歡在渲染中執行全部 if else then 邏輯,並且更喜歡在我的狀態下使用“加載”並在表單加載之前渲染一個很棒的字體微調器, http://fortawesome.github.io/Font-真棒/例子/ 這是重寫以向您展示我的意思。 如果我搞砸了 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 來獲取值。 如果你走這條路,我建議你有一個外殼組件(通常稱為高階組件)來獲取數據,然后將它作為道具傳遞給表單。

總的來說,我建議您通讀一遍 react 文檔並學習一些教程。 那里有很多博客, http://www.egghead.io有一些很好的教程。 我的網站上也有一些東西, http://www.openmindinnovations.com

也許不是最好的解決方案,但我會制作一個像下面這樣的組件,這樣我就可以在我的代碼中的任何地方重用它。 我希望它已經在默認情況下做出反應。

<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 

要強制 defaultValue 重新渲染,您需要做的就是更改輸入本身的鍵值。 這是你如何做到的。

<input 
type="text" 
key={myDynamicKey} 
defaultValue={myDynamicDefaultValue} 
placeholder="It works"/>

我正在嘗試使用react創建一個簡單的表單,但是要使數據正確綁定到表單的defaultValue面臨困難。

我正在尋找的行為是這樣的:

  1. 當我打開頁面時,應在數據庫中的“文本”輸入字段中填寫AwayMessage的文本。 那就是“樣本文本”
  2. 理想情況下,如果數據庫中的AwayMessage沒有文本,則希望在“文本”輸入字段中有一個占位符。

但是,現在,我發現每次刷新頁面時,“文本”輸入字段均為空白。 (盡管我在輸入中鍵入的內容可以正確保存並持久保存。)我認為這是因為當AwayMessage為空對象時,輸入文本字段的html會加載,而當awayMessage加載時,輸入文本字段的html不會刷新。 另外,我無法為該字段指定默認值。

為了清楚起見,我刪除了一些代碼(即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}

給參數“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}
    />

相關問題

在控件上設置defaulValue不會更新state

做反向工作完美:

  • state設置為默認值,控件 UI 會正確更新,就像給定了defaulValue

代碼:

let defaultRole = "Owner";

const [role, setRole] = useState(defaultRole);

useEffect(() => {
    setMsg(role);
});

const handleChange = (event) => {
    setRole(event.target.value );
};

// ----

<TextField
    label="Enter Role"
    onChange={handleChange}
    autoFocus
    value={role}
/>
  1. 為您的默認值定義一個狀態
  2. 用一個div和一個key道具包圍你的輸入
  3. 將鍵值設置為與輸入的 defaultValue 相同的值。
  4. 在某處調用您在步驟 1 中定義的setDefaultValue以重新渲染您的組件

例子:

const [defaultValue, setDefaultValue] = useState(initialValue);

useEffect(() => {
    setDefaultValue(initialValue);
}, false)

return (
    <div key={defaultValue}>
        <input defaultValue={defaultValue} />
    </div>
)

使用value而不是defaultValue並使用onChange方法更改輸入的值。

非常簡單,使 defaultValue 和 key 相同:

<input defaultValue={myVal} key={myVal}/>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM