2016-02-18 30 views
7

我有兩個組件:一個容器組件和一個表示組件。在功能(無狀態)組件中讀取<input>

容器使用演示組件獲取顯示Post所需的所有信息和操作。在展示的組件上,我有一種方法可以在呈現信息和編輯信息之間切換。當我編輯並提交有關帖子的數據時,我想從所有不同的輸入中讀取值,以便發送一個動作。

但是,在<form id='theForm' onSubmit={onHandleSubmit}>標記內的輸入是而不是。相反,在<form>之外的所有<input><button type='submit'>都具有form='theForm'屬性。

我以爲我可以有形式以外的許多<input>,但只要form屬性對相應<form>指出,我能讀懂它重視使用事件handleOnSubmit (e) {...}臨危。不過,我還沒有想出如何做到這一點。

如何讀取我的handleOnSubmit函數上的輸入值?或者這是一個完全錯誤的想法,我應該放棄?

// PostSummaryContainer.js 
import React, { PropTypes, Component } from 'react' 
import { connect } from 'react-redux' 

import { loadPost, editPost, editPostCancel, editPostSubmit } from '../../actions/posts' 

import PostSummaryView from '../../views/details/summary' 

class PostSummaryContainer extends Component { 
    constructor (props) { 
    super(props) 
    this.handleOnSubmit = this.handleOnSubmit.bind(this) 
    this.handleOnCancel = this.handleOnCancel.bind(this) 
    this.handleOnSubmit = this.handleOnSubmit.bind(this) 
    } 

    handleOnEdit (e) { 
    e.preventDefault() 
    this.props.editPost() 
    } 

    handleOnCancel (e) { 
    e.preventDefault() 
    this.props.editPostCancel() 
    } 

    handleOnSubmit (e) { 
    e.preventDefault() 

    // How do I read the input values? <-------------------- 
    } 

    componentWillMount() { 
    const { 
     id, 
     loadPost 
    } = this.props 

    loadPost(id) 
    } 

    render() { 
    const { 
     post, 
     isLoading, 
     isEditing 
    } = this.props 

    const viewProps = { 
     bacon, 
     isLoading, 
     isEditing, 
     handleOnEdit: this.handleOnEdit, 
     handleOnCancel: this.handleOnCancel, 
     handleOnSubmit: this.handleOnSubmit 
    } 

    return (
     <PostSummaryView {...viewProps} /> 
    ) 
    } 
} 

const mapStateToProps = (state, ownProps) => { 
    const { 
    params: { 
     id 
    } 
    } = ownProps 

    const post = state.entities.post[id] 

    const { 
    isLoading, 
    isEditing 
    } = state.posts 

    return { 
    id, 
    post, 
    isLoading, 
    isEditing 
    } 
} 

export default connect(
    mapStateToProps, 
    { loadPost, editPost, editPostCancel, editPostSubmit } 
)(PostSummaryContainer) 

在我的演示組件:

// PostSummmaryView.js 
import React from 'react' 
import moment from 'moment' 

function PostSummaryView (props) { 
    const { 
    post, 
    isLoading, 
    isEditing, 
    handleOnEdit, 
    handleOnCancel, 
    handleOnSubmit 
    } = props 

    const formId = 'editPostForm' 

    return (
    isLoading 
     ? <div>Loading...</div> 
     : <div className='row'> 
      {isEditing && <form id={formId} onSubmit={handleOnSubmit}><input type='text' name='name' /></form>} 

      <div className='col-md-6'> 
      <img src={post.media.url} className='img-responsive' /> 
      {isEditing && <input type='file' name='media' form={formId}/>} 
      </div> 
      <div className='col-md-6'> 

      <h1>{post.name}</h1> 
      <p> 
       {moment(post.publicationDate).format('dddd, MMMM Do')} 
      </p> 

      <hr /> 

      <p className='text-left'> 
       {post.description || 'Lorem ipsum dolor sit amet, consectetur adipisici elit...'} 
      </p> 

      {isEditing 
       ? <div> 
        <button className='btn btn-lg btn-default' onClick={handleOnCancel}>Cancel</button> 
        <button type='submit' className='btn btn-lg btn-default' form={formId}>Submit</button> 
       </div> 
       : <button className='btn btn-lg btn-default' onClick={handleOnEdit}>Edit</button> 
      } 

      </div> 
     </div> 
) 
} 

export default PostSummaryView 

回答

5

免責聲明:我還是新反應/終極版,所以採取這個答案有粒鹽。

我覺得你的做法是略有了,在你不需要提交(無論是內部還是外部的<form>)時從輸入去走一走,收集的任何數據。你的國家應該始終處於一箇中心,整合的地方。

考慮到您提供了取消選項,在編輯過程中更新狀態的單獨部分時更新Post數據比直接修改「源」Post數據更優雅(恕我直言)。

您可以爲編輯帖子表單創建一個縮減器,以保留輸入字段的鍵/值對。

當用戶開始編輯時,可以將原始發佈數據克隆到特定於「編輯」表單的狀態的新部分。當用戶改變輸入時,你可以發出行動說:「表單域X被更改爲值Y」,可以將其縮小到狀態而不用修改原始的發佈數據。在這個流程中的狀態對象的 僞代碼示例:

{ 
    // The actual Post data 
    post: { 
     media: {...}, 
     title: "My First Post", 
     publicationDate: 1455768160589, 
     description: "Lorem ipsum dolor sit amet"     
    }, 

    // The temporary Post data in the Edit form 
    postForm: { 
     media: {...}, 
     title: "My Turbo-Charged First Post", 
     publicationDate: 1455769951276, 
     description: "Updated description yadda blah"     
    } 
} 

然後,在你的演示組件,你可以開車輸入值關postForm而不是post

每個輸入將被給予改變的處理函數,以便更新被立即反映在狀態(或反映,這取決於你驗證邏輯/減速)。 即:

// In your actions associated with `Post` 
// ------------------------------------------ 
function updateForm(field, value) { 
    return { 
     type: UPDATE_FORM, 
     field, 
     value 
    } 
} 

// In your container 
// ------------------------------------------ 
handleOnEdit(event) { 
    postActions.updateForm(event.target.name, event.target.value) 
} 

// In your reducer 
// ------------------------------------------ 
switch (action.type) { 
    case UPDATE_FORM: 
     return { 
      ...state, 
      [action.field]: action.value 
     } 
} 

// In your presentational component's render() method 
// ------------------------------------------ 
const {postForm, handleOnEdit} = this.props 
const descriptionMarkup = (
    isEditing 
    ? <input type='text' name='description' value={postForm.description} onChange={handleOnEdit} /> 
    : (post.description || 'Lorem ipsum dolor sit amet, consectetur adipisici elit...') 
) 
// ... 
<p className='text-left'> 
    {descriptionMarkup} 
</p> 

如果按照這個模式(!又一遍,不知道它的「右」),提交表單隨着做你的國家的postForm對象的東西一樣簡單。該對象應始終反映最新和最大的表單輸入值。

取消表格變得與將狀態樹的postForm部分設置爲{}一樣簡單。原始的Post數據保持不變。

希望這有助於喚起一些想法......

一些其他的例子/方法你可以嘗試:通過

erikras
+1

啊。這似乎是一個好主意嘗試。明天我會檢查出來並報告它是如何發生的。謝謝! – Sparragus

+1

我試着實現這個或使用REDX形式。我在使用redux-form的文檔時遇到了困難,所以我放棄了它。我會探索你的未來項目的想法。最後,我最終重構了我的代碼,從功能組件到X類擴展了Component,並且讀取輸入變成了更容易的任務。我也擺脫了

和窗體屬性。不管怎麼說,多謝拉! – Sparragus

+0

太棒了,聽起來像一個很好的學習經驗 - 任何機會,你可以用你的重構解決方案更新你的問題? – rkd

相關問題