ReactJS:通过表单获取和更新数据的惯用方式是啥?
Posted
技术标签:
【中文标题】ReactJS:通过表单获取和更新数据的惯用方式是啥?【英文标题】:ReactJS: What is the idiomatic way to fetch and update data through a form?ReactJS:通过表单获取和更新数据的惯用方式是什么? 【发布时间】:2015-07-23 20:18:50 【问题描述】:我正在努力思考通过 html 表单更新数据的最佳方法。以 ReactJS 网页为例:
https://facebook.github.io/react/docs/tutorial.html
假设您希望实现让用户编辑她过去发布的评论的功能(即不在当前会话中,因此必须从服务器获取)。编辑评论页面需要预先填写评论的现有作者姓名和文本。您将如何实现获取评论数据和预填写评论表单?以下是我脑海中无法理清的相互矛盾的想法(我们称新组件为CommentEdit
):
CommentEdit
的道具,因为它们不是状态
CommentEdit
组件应该是可重用的,因此它应该能够从服务器本身获取初始数据,但随后必须将其保存为状态
如果 CommentEdit
的父级要获取并设置 CommentEdit
的 props,则必须将其保存为状态,因此没有太多节省
Flux 之类的东西可能会起作用,但 Flux 让我更加困惑。如果 Flux 要存储 cmets,它是否必须为用户保存每条评论?如果用户有数千个 cmets 会发生什么?
老实说,我只是希望组件可以更改自己的道具。似乎它会使组件更加可重用。
【问题讨论】:
【参考方案1】:老实说,我只是希望组件可以更改自己的道具。似乎它会使组件更加可重用。
并非如此,可以更改自己的 props 的组件并不比那些不能更改的组件更可重用,只是它们的底层实现会变得更加复杂。
当前react.js
流与数据下降和事件冒泡使组件“非常”确定性,因为在组件生命周期中的任何时候,您都知道组件将根据您给它的输入生成什么输出。这在调试和单元测试应用程序时也很有帮助。
现在,让您进退两难的是,CommentEdit
只需要一个content
属性,因为作者不会更改,并且始终是登录网站的人。其他状态不是必需的,因为当用户单击save
按钮时,编辑的内容会冒泡,并且当存储在组件祖先之一的state
中的comments
列表将插入列表时更新。
如果您为每个评论正确设置了key
属性,那么react 会很好地注意到已编辑评论的html 元素不需要重新创建,只需渲染html 元素的innerHTML
评论需要更改。
如果您想显示作者,可以将其添加为道具,除非您想使用此布局构建多个站点,否则它不会影响/改进组件本身。
【讨论】:
感谢您的回复。虽然在这种情况下content
是唯一的属性,但如果组件有很多属性怎么办?这不会要求父组件保持其状态的所有属性吗?
根据数据模型和 UI,子组件的属性可能需要从状态中检索,或者可以从自己的属性中推断出来。它仍然是一种更简洁的设计,因为数据仅在一个方向流动,这使您的应用程序架构更加健壮。【参考方案2】:
我最终通过为我的每个组件添加一个“包装器”父级来解决这个问题。包装器组件负责从服务器获取数据,并将其存储在其状态中。包装器会将获取的状态作为道具传递给它的孩子。然后我将这个设置抽象为 mixin,创建了一个包装混合和包装子混合,以便我可以轻松地重用这个设置。
这种模式非常适用于您应用中的典型表单。包装器将获取数据以预填充表单,子节点将表单发送到服务器并负责错误处理。
这是一个例子:
// This handles the form submission and error handling
var EditFormMixin =
getInitialState: function()
return formState:FORM_STATE_EDITING, errors:
,
handleSubmitBase: function(event, url, data, method, success, error)
event.preventDefault();
this.setState(formState:FORM_STATE_SUBMITTING, errors:);
$.ajax(
url: url,
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),
method: method,
success: function(data)
this.setState(formState:FORM_STATE_SUBMITTED);
if (success)
success();
;
.bind(this),
error: function(xhr, status, err)
this.setState(formState:FORM_STATE_EDITING);
if (xhr.status == 400)
this.setState(errors:xhr.responseJSON);
if (error)
error();
.bind(this)
);
;
// This handles fetching the initial data for the form
var EditFormWrapperMixin =
getInitialState: function()
return data: , loadState:LOAD_STATE_UNLOADED, url:this.getUrl();
,
fetch: function()
this.setState(loadState:LOAD_STATE_LOADING)
$.ajax(
url: this.state.url,
dataType: "json",
method: "GET",
success: function(data)
this.setState(data:data, loadState:LOAD_STATE_LOADED);
.bind(this),
error: function(xhr, status, err)
.bind(this)
);
componentDidMount: function()
this.fetch();
,
componentWillReceiveProps: function(nextProps)
var url = this.getUrl();
this.setState(url:url, function()
this.fetch();
);
;
【讨论】:
【参考方案3】:Flux 是您可以用来从应用程序中获取数据的最佳工具,您不必在组件内部使用状态,使用 props 来收取初始数据,然后使用 react.DOMNode 从每个元素中获取数据你需要https://facebook.github.io/react/docs/top-level-api.html#react.finddomnode的表单,在所有表单组件中也使用refs,最后你可以使用flux将你的数据发送到服务器并保存。
【讨论】:
以上是关于ReactJS:通过表单获取和更新数据的惯用方式是啥?的主要内容,如果未能解决你的问题,请参考以下文章