2016-02-18 9 views
7

Ich habe zwei Komponenten: eine Container-Komponente und eine Präsentationskomponente.Lesen in einer funktionalen (zustandslosen) Komponente

Der Container ruft alle Informationen und Aktionen ab, die zum Anzeigen eines Posts mit der Präsentationskomponente erforderlich sind. Auf der Präsentationskomponente habe ich eine Möglichkeit, zwischen der Darstellung und Bearbeitung der Information zu wechseln. Wenn ich die Daten über den Beitrag bearbeite und absende, möchte ich die Werte von all den verschiedenen Eingaben lesen, die ich habe, damit ich eine Aktion versenden kann. Die Eingänge sind nicht innerhalb eines <form id='theForm' onSubmit={onHandleSubmit}> Tags. Stattdessen haben alle <input> und <button type='submit'>, die außerhalb der <form> sind, ein form='theForm' Attribut.

Ich dachte, dass ich viele <input> außerhalb der Form, aber solange das form Attribut wies auf die entsprechende <form> haben, konnte ich es Werte mit dem Fall, dass handleOnSubmit (e) {...} BEKOMMT lesen konnte. Ich habe jedoch nicht herausgefunden, wie das geht. Wie kann ich die Werte der Eingänge auf meiner handleOnSubmit Funktion lesen? Oder ist das eine völlig falsche Idee, die ich aufgeben sollte?

// 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) 

Auf meiner Präsentationskomponente:

// 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 

Antwort

5

Haftungsausschluss: Ich bin noch neu in React/Redux, so nehmen Sie diese Antwort mit einem großen Salzkorn.

Ich denke, Ihr Ansatz leicht ausgeschaltet ist, dass Sie nicht benötigen, sollten um zu gehen und alle Daten von den Eingängen zu sammeln, wenn (ob innerhalb oder außerhalb der <form>) einreichen. Dein Staat sollte immer an einem zentralen, konsolidierten Ort sein.

Wenn Sie eine Cancel-Option angeben, ist das Beibehalten der Post-Daten während eines Edits in einem separaten Teil des Status eleganter (IMHO) als direktes Ändern der "Quell" -Post-Daten.

Sie könnten einen Reducer für das Formular "Post bearbeiten" erstellen, das Schlüssel/Wert-Paare für die Eingabefelder enthält.

Wenn ein Benutzer mit der Bearbeitung beginnt, können Sie die ursprünglichen Post-Daten in diesen neuen Teil des für das Bearbeitungsformular spezifischen Status kopieren. Wenn der Benutzer die Eingaben ändert, können Sie Aktionen versenden, die sagen "Hey, Formularfeld X wurde in Wert Y geändert", der auf den Status ohne geändert werden könnte, indem die ursprünglichen Postdaten geändert werden. Pseudo-Code Beispiel für den Zustand Objekt in dieser Strömung:

{ 
    // 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"     
    } 
} 

Dann in Ihrer Präsentationskomponente, können Sie den Eingang fahren Werte postForm statt post ab.

Jedem Eingang wird eine Änderungs- handlerfunktion zugewiesen, so dass Aktualisierungen sofort in dem Status widergespiegelt werden (oder nicht reflektiert, abhängig von Ihrer Validierungslogik/-reduktionen). , d.h.: So einfach wie etwas zu tun mit Ihrem staatlichen postForm Objekt

// 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> 

Wenn Sie diesem Muster folgen (! Und wieder nicht sicher, dass es „richtig“), wird das Formular absenden. Dieses Objekt sollte immer die neuesten und größten Formulareingabewerte enthalten.

Das Abbrechen des Formulars wird so einfach wie das Festlegen des postForm-Teils des Statusbaums auf {}. Die ursprünglichen Post-Daten bleiben gleich.

Hope this einige Ideen hilft joggen ...

Einige andere Beispiele/Ansätze, die Sie könnten versuchen:

+1

Ah. Dies scheint eine gute Idee zu sein. Morgen werde ich es überprüfen und berichten, wie es gelaufen ist. Vielen Dank! – Sparragus

+1

Ich habe versucht, dies zu implementieren oder Redux-Form zu verwenden. Ich hatte Schwierigkeiten mit der Dokumentation von redux-form, also gab ich es auf. Und ich werde Ihre Idee für ein zukünftiges Projekt erkunden. Am Ende habe ich meinen Code von funktionalen Komponenten in Klasse X erweitert und erweitert. Ich habe auch die

und die Formularattribute losgeworden. Trotzdem danke! – Sparragus

+0

Großartig, klingt nach einer guten Lernerfahrung - Sie könnten Ihre Frage mit Ihrer refaktorierten Lösung aktualisieren? – rkd

Verwandte Themen