如何处理同构渲染表单的早期输入

IT技术 forms reactjs isomorphic-javascript
2021-05-04 17:40:12

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

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

更新

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

2个回答

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

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

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

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

建议的解决方案:

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

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

如果我理解正确,这就是正在发生的事情: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 请求来获取预填充的数据,如果用户尚未输入某些输入,则更新输入。