8

我有一个包含表单的 React 应用程序,该表单在服务器端呈现,预先填充了用户正在进行的工作。问题在于,如果用户在应用加载之前编辑表单中的值,那么应用就不会意识到更改。当用户保存时,服务器渲染的未更改数据被重新保存,并且用户的新数据被丢弃,尽管它仍然显示在表单中。简而言之,React 和最初加载时替换的标记中的输入值之间似乎存在脱节。

我想我可以将 refs 放在每个输入上,并将它们的值复制到 componentDidMount 上的应用程序状态中,但必须有更好的方法。有没有其他人解决过这个问题?

更新

我现在认为解决这个问题的最好方法是让 React 在创建校验和时考虑输入值。GH问题:https ://github.com/facebook/react/issues/4293

4

2 回答 2

3

我想我可以将 refs 放在每个输入上,并将它们的值复制到 componentDidMount 上的应用程序状态中,但必须有更好的方法。有没有其他人解决过这个问题?

浏览器自动填充字段或在刷新时记住以前的值也可能导致实际上相同的问题 - 您的应用程序对数据的视图与用户的不同。

我过去的蛮力解决方案是从其输入中提取完整的表单状态onSubmit并在允许提交之前重新运行验证。

按照您的建议使用componentDidMount听起来像是一个更优雅的解决方案,因为它可以避免用户输入无效数据并被允许在收到任何警告之前尝试提交它。但是,您不需要ref为每个输入添加 a;只需添加一个<form>并使用它的.elements集合来提取所有数据。

建议的解决方案:

  1. componentDidMount()中,从中提取表单的数据(为此,我从表单库中.elements提取了get-form-data )
  2. 根据您应用的状态检查每个字段的当前值。
  3. 如果字段的当前值不同,则将其视为通过事件到达的新用户输入 - 在状态中更新它并重新运行任何关联的验证例程。

然后从那componentDidMount()以后,您的应用程序和用户将始终在同一页面上(字面意思)。

于 2015-07-05T20:49:57.473 回答
0

如果我理解正确,这就是正在发生的事情:https ://jsfiddle.net/9bnpL8db/1/

var Form = React.createClass({
    render: function () {
        return <div>
            <input type="text" defaultValue={this.props.defaultValue}/>
        </div>;
    }
});

// Initial form render without server-side data
React.render(<Form/>, $('#container')[0]);

setTimeout(function () {
    // Simulate server-side render
    $('#container').html(
        // overwrites input
        React.renderToString(<Form defaultValue="server1"/>)
    );
}, 5000);

不应使用服务器端渲染进行更新。相反,应该使用服务器端渲染来创建初始页面,在用户有机会进行更改之前填充输入。为了解决你的问题,我认为你有几个选择:

  1. 使用服务器端渲染来渲染初始页面,使用保存的数据预填充输入。使用此选项,用户永远不会看到没有保存数据的页面。这消除了用户开始输入输入然后该输入被服务器覆盖的问题。
  2. 使用客户端呈现来呈现页面并使用 GET 请求来获取预填充的数据,如果用户尚未输入某些输入,则更新输入。
于 2015-07-05T06:14:40.333 回答