Redux-Form Field 不会更新其中的 <input> 值

Redux-Form Field won't update with value of <input> inside it

我正在尝试在 React 中设计一个可输入的输入组件,它被包装在一个 Redux-Form Field 中。但是当 HTML <input> 标签的值改变时 Field 的值不会更新。

Field定义为:

<Field
    name="inputTextBox"
    type="text"
    component={CustomInputComponent}
</Field>

CustomInputComponent 定义为:

    class CustomInputComponent extends Component {

        constructor() {
            super();
            this.state= {
                value: undefined
            };

        /* updates the state of CustomInputComponent with the current value typed inside <input> */
        setInputValueText = (value) => {
            this.setState({
                ...this.state,
                value
            })
        };

        render() {
            return (
                <input type="text" value={this.state.value} onInput={event => this.setInputValueText(event.target.value)} />
            )

    }

每当输入 <input> 标签时,CustomInputComponent 的状态会成功更改,但上面包含 CustomInputComponentField 的值不会改变。我正在尝试通过以下方式访问 Field 的值:

const selector = formValueSelector('myForm')
let currentInput = selector(state, 'inputTextBox')

我希望 currentInput 包含在 input 中键入的当前值。我可能缺少什么?

几种方法:

  • 将 Redux 表单 Field 的 data/methods 传递给 child(推荐——最低要求见下文) .
  • 利用 React 状态,将其设置为 Redux 字段,然后从 parentchild.

https://codesandbox.io/s/z3xnjv4w7m(将 Redux 字段 data/methods 传递给 child) https://codesandbox.io/s/m4x7z7o429(通过 React state 控制 Redux Fields)


将 Redux 字段的 Data/Methods 传递给 Child 示例

InputForm.js

import React, { Component } from "react";
import { Form, Field, reduxForm } from "redux-form";
import CustomInputComponent from "./customInputComponent";

const isRequired = value => (!value ? "Required" : undefined);

class InputForm extends Component {
  handleFormSubmit = ({ inputTextBox }) =>
    alert(`Value of custom input: ${inputTextBox}`);

  render = () => (
    <div style={{ height: 300, width: 500 }}>
      <h1 style={{ textAlign: "center" }}>Input Form</h1>
      <hr />
      <Form onSubmit={this.props.handleSubmit(this.handleFormSubmit)}>
        <div style={{ height: 70 }}>
          <Field
            className="uk-input"
            component={CustomInputComponent}
            name="inputTextBox"
            type="text"
            placeholder="Write something..."
            validate={[isRequired]}
          />
        </div>
        <button
          type="submit"
          className="uk-button uk-button-primary uk-button-large"
          disabled={this.props.submitting}
        >
          Submit
        </button>
        <button
          type="button"
          className="uk-button uk-button-default uk-button-large"
          disabled={this.props.pristine || this.props.submitting}
          onClick={this.props.reset}
          style={{ float: "right" }}
        >
          Clear
        </button>
      </Form>
    </div>
  );
}

export default reduxForm({ form: "InputForm" })(InputForm);

customInputField.js

import React, { Fragment } from "react";

export default ({
  children,
  input,
  meta: { invalid, touched, error },
  ...props
}) => (
  <Fragment>
    <input {...input} {...props} />
    {touched && error && <div style={{ color: "red" }}>{error}</div>}
  </Fragment>

最低要求

至少,Redux Field 的 input.onChange 方法和 input.value 需要从 parent 传递到 child。

Parent

<Field
   component={CustomInputComponent}
   name="inputTextBox"
/>  

Child

export default ({ input: { onChange, value }}) => (
  <input
    type="text"
    placeholder="Write something..."
    className="uk-input"
    onChange={onChange}
    value={value}
  />
);

通过 React 状态控制字段

控制InputForm.js

import React, { Component } from "react";
import { Form, Field, reduxForm, change } from "redux-form";
import CustomInputComponent from "./customInputComponent";

const isRequired = value => (!value ? "Required" : undefined);

class ControlledInputForm extends Component {
  state = { value: "" };

  handleFormSubmit = ({ inputTextBox }) =>
    alert(`Value of custom input: ${inputTextBox}`);

  handleChange = e => {
    this.setState({ value: e.target.value }, () => {
      this.props.change("inputTextBox", this.state.value);
    });
  };

  resetForm = () => this.setState({ value: "" }, () => this.props.reset());

  render = () => (
    <div style={{ height: 300, width: 500 }}>
      <h1 style={{ textAlign: "center" }}>Controlled Input Form</h1>
      <hr />
      <Form onSubmit={this.props.handleSubmit(this.handleFormSubmit)}>
        <div style={{ height: 70 }}>
          <Field
            className="uk-input"
            component={CustomInputComponent}
            name="inputTextBox"
            placeholder="Write something..."
            type="text"
            handleChange={this.handleChange}
            controlledValue={this.state.value}
            validate={[isRequired]}
          />
        </div>
        <button
          type="submit"
          className="uk-button uk-button-primary uk-button-large"
          disabled={this.props.submitting}
        >
          Submit
        </button>
        <button
          type="button"
          className="uk-button uk-button-default uk-button-large"
          disabled={this.props.pristine || this.props.submitting}
          onClick={this.resetForm}
          style={{ float: "right" }}
        >
          Clear
        </button>
      </Form>
    </div>
  );
}

export default reduxForm({
  form: "ControlledInputForm",
  fields: ["inputTextBox"]
})(ControlledInputForm);

customInputComponent.js

import React, { Fragment } from "react";

export default ({
  meta: { invalid, touched, error },
  handleChange,
  controlledValue,
  ...props
}) => (
  <Fragment>
    <input {...props} value={controlledValue} onChange={handleChange} />
    {touched && error && <div style={{ color: "red" }}>{error}</div>}
  </Fragment>
);