在功能性(无状态)组件中读取 <input>
Posted
技术标签:
【中文标题】在功能性(无状态)组件中读取 <input>【英文标题】:Read <input> in a functional (stateless) component 【发布时间】:2016-05-30 01:50:51 【问题描述】:我有两个组件:一个容器组件和一个展示组件。
容器获取使用展示组件显示帖子所需的所有信息和操作。在展示组件上,我有一种方法可以在展示信息和编辑信息之间切换。当我编辑和提交有关帖子的数据时,我想从我拥有的所有不同输入中读取值,以便我可以调度一个操作。
但是,输入不是在<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
【问题讨论】:
【参考方案1】:免责声明:我还是 React/Redux 的新手,所以请对这个答案持保留态度。
我认为您的方法有点不正确,因为您在提交时不需要四处走动并从输入中收集任何数据(无论是在<form>
内部还是外部)。您的州应该始终处于一个集中、统一的位置。
鉴于您提供了一个取消选项,在编辑期间将发布数据保持在状态的单独部分更新比直接修改“源”发布数据更优雅(恕我直言)。
您可以为 Edit Post 表单创建一个 reducer,为输入字段保留键/值对。
当用户开始编辑时,您可以将原始 Post 数据克隆到特定于 Edit 表单的状态的这个新部分。当用户更改输入时,您可以发送操作说“嘿,表单字段 X 已更改为值 Y”,这可以减少到状态 修改原始 Post 数据。 本流程中状态对象的伪代码示例:
// 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
。
每个输入都会被赋予一个更改处理函数,因此更新会立即反映在状态中(或不反映,具体取决于您的验证逻辑/reducer)。 即:
// 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 数据保持不变。
希望这有助于激发一些想法......
您可以尝试其他一些示例/方法:
redux-form 埃里克拉斯 stateless-form-examples by nackjicholson redux-form-example【讨论】:
啊。这似乎是一个尝试的好主意。明天我会检查它并报告它的进展情况。谢谢! 我尝试实现这个或使用 redux-form。我很难使用 redux-form 的文档,所以我放弃了它。我将探讨您对未来项目的想法。最后,我最终将我的代码从功能组件重构为类 X 扩展组件,并且读取输入变得更加容易。我还摆脱了 太棒了,听起来像是一次很好的学习体验——你有没有机会用你重构的解决方案更新你的问题? 我最终使用了redux-form
,效果很好!最初我发现文档非常混乱并且缺乏好的示例,但在几天后重新访问它之后,它是有道理的。所以这就是我最终做的!感谢您的想法和建议。干杯!
我不会说这是解决方案,而是解决 OP 问题的方法。从技术上讲,您可以使用 document.querySelector
获取输入字段的值并将其传递给您的 submit
处理程序,但这会破坏让库为您处理它的目的,所以我建议您宁愿坚持有状态的组件,因为它确实在您的应用程序中保存了某种形式的状态。因此,这不是您正在寻找的答案,但在这种情况下使用有状态组件会更有意义。以上是关于在功能性(无状态)组件中读取 <input>的主要内容,如果未能解决你的问题,请参考以下文章
如何在 React Native 的无状态功能组件中扩展原生组件的 props TypeScript 接口?
React,Typescript中无状态功能组件内的事件处理
当组件是无状态功能时,通过显示名称查找组件,使用 Enzyme