109

反応を使用して単純なフォームを作成しようとしていますが、データをフォームの 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}
4

9 に答える 9

71

defaultValue は初期ロード専用です

入力を初期化する場合は defaultValue を使用する必要がありますが、state を使用して値を変更する場合は、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} />

また、実際に値を「プレースホルダー テキスト」に設定するため、プレースホルダー テキストを渡したくありません。undefined と nil は値を本質的に defaultValue に変えるため、空白の値を入力に渡す必要があります。https://facebook.github.io/react/tips/controld-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 .

変更と読み込み状態で書き直す

個人的には、そうでなければレンダリングでロジックをすべて実行するのは好きではなく、私の状態で「読み込み」を使用し、フォームが読み込まれる前にフォントの素晴らしいスピナーをレンダリングすることを好みます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>

それはそれについてカバーするはずです。これは、状態と値を使用するフォームについての 1 つの方法です。値の代わりに defaultValue を使用し、送信時に refs を使用して値を取得することもできます。そのルートに行く場合は、データを取得してフォームに小道具として渡すための外部シェル コンポーネント (通常は高次コンポーネントと呼ばれます) を用意することをお勧めします。

全体として、react ドキュメントを最後まで読み、いくつかのチュートリアルを行うことをお勧めします。そこにはたくさんのブログがあり、http://www.egghead.ioにはいくつかの優れたチュートリアルがありました。私のサイトhttp://www.openmindinnovations.comにもいくつかのものがあります。

于 2015-05-10T07:48:03.810 に答える
3

最善の解決策ではないかもしれませんが、以下のようなコンポーネントを作成して、コードのどこでも再利用できるようにします。デフォルトですでに反応していたらいいのにと思います。

<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 
于 2015-05-09T23:38:26.720 に答える
1

それは非常に簡単です。defaultValue とキーを同じにします。

<input defaultValue={myVal} key={myVal}/>
于 2021-10-15T21:32:14.537 に答える
1

関連する問題

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}
/>
于 2021-02-17T03:43:06.053 に答える
0
  1. デフォルト値の状態を定義する
  2. div入力を aとkeypropで囲みます
  3. キー値を入力の defaultValue と同じ値に設定します。
  4. ステップ 1 で定義したものをどこかで呼び出してsetDefaultValue、コンポーネントを再レンダリングします

例:

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

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

return (
    <div key={defaultValue}>
        <input defaultValue={defaultValue} />
    </div>
)
于 2021-06-17T11:46:24.457 に答える