从 Redux Form v6.0.0 外部提交按钮

Submit button from outside Redux Form v6.0.0

此问题与 Redux Form v6.0.0 有关(在撰写此问题时它是 v6.0.0-alpha.15)。

如何从表单组件外部获取表单验证状态(如 pristinesubmittinginvalid)?

我举个例子。这是 "classical redux-form" pseudo-structure:

<Form(MyExampleForm)>
    <MyExampleForm>
        <input name="title" ... />
        <submit-button />

...其中 <submit-button> 在 JSX 中看起来像这样:

<button type="submit" disabled={pristine || submitting || invalid} >Save</button>

但是在我的应用程序中,我的提交按钮必须在表单之外,放置在应用程序中的不同位置(假设在应用程序 header 中,在整个应用程序的顶部)。

  1. 如何从 Redux-Form 之外获取 pristinesubmittinginvalid? (没有真正讨厌的黑客攻击,如果可能:-)
  2. 我如何提交该表格?

redux-form works with React Redux to enable an html form in React to use Redux to store all of its state.

如果"outside of Redux-Form"表示仍然是 redux 应用程序,您可以尝试通过调度一些操作来将这些属性存储在状态中。

在表单中:您正在检测正在发生的事情(当它无效时等),调度一个动作来修改状态, 在 "outside" 部分:您将适当的 属性 传递给组件(与您需要的组件),并取决于您是否禁用按钮。

也许你可以看看 Instance API of redux-forms. It provides access to a submit() method on an instance of your decorated form component. There is also a pristine Boolean property and an invalid Boolean property available (there is a request 来公开提交 属性)。

这里有一个示例:http://redux-form.com/5.3.1/#/examples/submit-from-parent?_k=jgv0m4(示例适用于 5.3.1,但过程与使用实例 API 的 v6 类似)

基本思路是,通过在表单中​​添加 ref="myExampleForm",您可以使用 this.refs.myExampleForm 传递它。然后,您可以检查实例的属性或调用 submit() 方法(或公开的任何其他方法)。

如果我们谈论的只是提交表单,那么您应该为您的 redux connect() 函数提供 {withRef: true} option

考虑具有子 RowDetail 组件的 Row 组件,该组件具有应从 Row 中保存的信息。

RowDetail 在这种情况下可以这样创建:

import { connect } from 'react-redux';
import { reduxForm } from 'redux-form';

const RowDetailForm = reduxForm({form: 'row-detail-form'})(RowDetail);

export default connect(mapStateToProps, null, null, {withRef: true})(RowDetailForm);

然后,在您的父组件 (Row) 中创建具有 ref 属性的表单:

<RowDetailForm ref={'rowDetailForm'} .../>  

现在提交是'easy':

onSave() {
  this.refs.rowDetailForm.getWrappedInstance().submit();
}

如果我们谈论的是原始属性和其他表单属性,那么您可以尝试从 parent 组件中的 mapStateToProps 函数中获取它们。

const rowDetailFormName = 'row-detail-form';
const mapStateToProps = (state) => ({
  rowDetailForm: state.form[rowDetailFormName]
});

但是这种方式似乎有点老套,因为据我了解 redux-form API 所有表单状态都不是直接访问的。如有错误请指正

在最新的 redux-form 版本 6.0.2 中:

  1. 可以通过选择器 http://redux-form.com/6.0.2/docs/api/Selectors.md/

    [=24= 访问表单状态 pristinesubmittinginvalid ]
  2. 可以导出 redux 形式的 action creators http://redux-form.com/6.0.2/docs/api/ActionCreators.md/

只需用相同的表单名称装饰另一个组件,您就可以在那里访问相同的状态变量。您还可以从父级传递 onSubmit 函数,并能够从您定义它们的任何地方提交所有 Field 值,因为它们都来自 redux 状态,而不是当前表单实例的 HTML 。 (这是一种 "hacky" 方式,但感觉不错)

提交函数是从父级定义的,不在状态中共享,因此您可以为每个实例设置不同的函数。

class MySubmitForm extends React.Component {
    render() {
        return (
            <button
                onClick={this.props.handleSubmit}
            >
                {this.props.pristine ? 'pristine' : 'changed'}
            </button>
        )
    }
}

export default reduxForm({
    form: 'myFormName'
})(MySubmitForm);

现在更容易做到这一点。您可以在具有按钮的独立组件中调用提交操作。

看这个例子: https://redux-form.com/7.1.2/examples/remotesubmit/

我最近不得不解决这个问题。我最终将回调传递给表单,每次我感兴趣的属性发生变化时都会调用该回调。 我使用 componentDidUpdate 生命周期方法来检测变化。

这应该适用于任何版本的库。

这是一个 post 示例代码 - http://nikgrozev.com/2018/06/08/redux-form-with-external-submit-button/