Read the <input> in the functional (non-standing) component

I have two components: one container component and one presentation component.

The container retrieves all the information and actions necessary to display the message using the presentation component. On the presentation component, I have a way that I can switch between the presentation of information and its editing. When I edit and send data about the record, I want to read the values โ€‹โ€‹from all the different inputs that I have, so I can send the action.

However, the input is not inside the <form id='theForm' onSubmit={onHandleSubmit}> . Instead, all <input> and <button type='submit'> that are outside the <form> have the attribute form='theForm' .

I thought that I could have a lot of <input> outside the form, but as long as the form attribute points to the corresponding <form> , I could read its values โ€‹โ€‹using the event that handleOnSubmit (e) {...} receives. However, I did not understand how to do this.

How can I read the input values โ€‹โ€‹of my handleOnSubmit function? Or is this a completely wrong idea that I should leave?

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

In my presentation component:

 // 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 
+7
javascript html reactjs forms redux
source share
1 answer

Disclaimer: I'm still new to React / Redux, so take this answer with a lot of salt.

I think your approach is a bit off, as you donโ€™t need to go around and collect any data from the inputs when sending (inside or outside the <form> ). Your state should always be in one central, consolidated place.

Given that you provide the Cancel option, saving Post data updated during editing in a separate part of the state is more elegant (IMHO) than directly modifying the "original" Post data.

You can create a reducer for the "Edit Message" form, which stores key / value pairs for input fields.

When the user starts editing, you can clone the original Post data into this new part of the form-specific state. When the user changes the input, you can send actions saying: โ€œHey, the form field X has been changed to Yโ€, which could be reduced to a state without changing the original Post data. An example of the pseudocode of a state object in this thread:

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

Then, in the presentation component, you can disable the input values โ€‹โ€‹of postForm instead of post .

Each input will be provided with a change handler function so that updates are immediately reflected in the state (or not reflected depending on your logic / gearbox). i.e:.

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

If you follow this pattern (and again, not sure if this is correct)! Submitting a form becomes as simple as doing something with your postForm state. This object should always reflect the input and input values โ€‹โ€‹of the last and largest form.

Canceling a form becomes as simple as setting the postForm part of the postForm tree to {} . The original Post data remains unchanged.

Hope this helps sort out some ideas ...

Some other examples / approaches you could try:

+5
source share

All Articles