Redux-Form字段不会使用其中的<input />值更新

时间:2018-09-12 20:36:26

标签: reactjs redux react-redux redux-form

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

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的状态都会成功更改,但是包含Field的上方CustomInputComponent的值不会更改。我正在尝试通过以下方式访问Field的值:

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

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

1 个答案:

答案 0 :(得分:1)

几种方法:

  • 将Redux表单字段的数据/方法传递给子项(推荐-有关最低要求,请参见下文)。
  • 利用React状态,将其设置为Redux字段,然后从 孩子父母

https://codesandbox.io/s/z3xnjv4w7m(将Redux Field数据/方法传递给子级) https://codesandbox.io/s/m4x7z7o429(通过React状态控制Redux字段)


将Redux字段的数据/方法传递给子示例

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从父级传递到子级。

父母

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

孩子

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

通过反应状态控制的字段

ControlledInputForm.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>
);