React.js表单 - 如何在最终页面上包含所有值?

3

我使用React-Final-Form构建了一个向导表单,用于我的注册页面。我正在努力找出如何在最终页面上显示所有用户输入,以便用户在提交之前进行双重检查/验证。如果有帮助,将不胜感激!

(附言:在发布之前,我尝试过研究这个问题,但我只能找到将用户输入存储在Redux中并从那里访问它们的方法,如果可能的话,我想避免这种方法。)

这是一个示例链接,展示了我想要做的事情 - 如果你正在寻找解决方案,请随意fork和玩耍!https://codesandbox.io/s/0332k02x0v

这里是代码,缩短为仅包含相关部分:

我的Wizard.js页面:

import React, { Component } from "react";
import PropTypes from "prop-types";
import { Form } from "react-final-form";

class Wizard extends Component {
  static propTypes = {
    onSubmit: PropTypes.func.isRequired
  };
  static Page = ({ children }) => children;

  constructor(props) {
    super(props);
    this.state = {
      page: 0,
      values: props.initialValues || {}
    };
  }
  next = values =>
    this.setState(state => ({
      page: Math.min(state.page + 1, this.props.children.length - 1),
      values
    }));

  previous = () =>
    this.setState(state => ({
      page: Math.max(state.page - 1, 0)
    }));

  validate = values => {
    const activePage = React.Children.toArray(this.props.children)[
      this.state.page
    ];
    return activePage.props.validate ? activePage.props.validate(values) : {};
  };

  handleSubmit = values => {
    const { children, onSubmit } = this.props;
    const { page } = this.state;
    const isLastPage = page === React.Children.count(children) - 1;
    if (isLastPage) {
      return onSubmit(values);
    } else {
      this.next(values);
    }
  };

  render() {
    const { children } = this.props;
    const { page, values } = this.state;
    const activePage = React.Children.toArray(children)[page];
    const isLastPage = page === React.Children.count(children) - 1;
    return (
      <Form
        initialValues={values}
        validate={this.validate}
        onSubmit={this.handleSubmit}
      >
        {({ handleSubmit, submitting, values }) => (
          <form onSubmit={handleSubmit}>
            {activePage}
            <div className="buttons">
              {page > 0 && (
                <button type="button" onClick={this.previous}>
                  « Previous
                </button>
              )}
              {!isLastPage && <button type="submit">Next »</button>}
              {isLastPage && (
                <button type="submit" disabled={submitting}>
                  Submit
                </button>
              )}
            </div>

            {/* <pre>{JSON.stringify(values, 0, 2)}</pre> */}
          </form>
        )}
      </Form>
    );
  }
}

export default Wizard;

我的index.js页面:

import React, { Component } from "react";
import { Field } from "react-final-form";
import formatString from "format-string-by-pattern";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import Wizard from "./Wizard";
import Styles from "./Styles";
import { addUser } from "../../../actions/authActions";

class ReactFinalForm2 extends Component {
  state = {};
  render() {
    const onSubmit = async values => {
      this.props.addUser(values);
      // API query here
    };

    const Error = ({ name }) => (
      // Error handing here
    );

    return (
      <Styles>
        <div>
          <Wizard initialValues={{}} onSubmit={onSubmit}>
            <Wizard.Page
              validate={values => {
                // Page validation here
              }}
            >
              // Page inputs here
            </Wizard.Page>
            <Wizard.Page
              validate={values => {
                // Page validation here
              }}
            >
              // Page inputs here
            </Wizard.Page>
            <Wizard.Page
              validate={values => {
                // Page validation here
              }}
            >
              // Page inputs here
            </Wizard.Page>
            <Wizard.Page>
              {/* *** THIS IS WHERE I WOULD LIKE TO DISPLAY ALL PREVIOUS VALUES (SO THE USER CAN CONFIRM / DOUBLE-CHECK THEIR INPUTS BEFORE SUBMITTING) *** */}
            </Wizard.Page>
          </Wizard>
        </div>
      </Styles>
    );
  }
}

ReactFinalForm2.propTypes = {
  addUser: PropTypes.func.isRequired
};

export default connect(
  null,
  { addUser }
)(ReactFinalForm2);
1个回答

2
我在父组件中添加了一个状态。每次子组件提交时都会更改此状态。我在父组件中将该状态进行了 JSON stringify。正如你所说,不需要使用 redux,这是我想出的解决方法。尽管如此,你的代码还有改进的潜力。请查看此工作范例:
[https://codesandbox.io/s/zrvloq4o6x]
Wizard.js 更改
  handleSubmit = values => {
    const { children, onSubmit } = this.props;
    const { page } = this.state;
    const isLastPage = page === React.Children.count(children) - 1;
    if (isLastPage) {
      return onSubmit(values);
    } else {
      this.next(values);
    }
    // Change added
    this.props.onStateChange(values);
  };

Index.js

import React from "react";
import { render } from "react-dom";
import Styles from "./Styles";
import { Field } from "react-final-form";
import Wizard from "./Wizard";

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

const onSubmit = async values => {
  await sleep(300);
  window.alert(JSON.stringify(values, 0, 2));
};

const Error = ({ name }) => (
  <Field
    name={name}
    subscribe={{ touched: true, error: true }}
    render={({ meta: { touched, error } }) =>
      touched && error ? <span>{error}</span> : null
    }
  />
);

const required = value => (value ? undefined : "Required");
let data = {};

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.onStateChange = this.onStateChange.bind(this);
  }

  onStateChange = values => {
    this.setState({ data: values });
    console.log(values);
  };
  render() {
    return (
      <Styles>
        <h1> React Final Form Example</h1>
        <h2>Wizard Form</h2>
        <a href="https://github.com/erikras/react-final-form#-react-final-form">
          Read Docs
        </a>
        <p>
          Notice the mixture of field-level and record-level (or{" "}
          <em>page-level</em> in this case) validation.
        </p>
        <Wizard
          initialValues={{}}
          onStateChange={this.onStateChange}
          onSubmit={onSubmit}
        >
          <Wizard.Page>
            <div>
              <label>First Name</label>
              <Field
                name="firstName"
                component="input"
                type="text"
                placeholder="First Name"
                validate={required}
              />
              <Error name="firstName" />
            </div>
            <div>
              <label>Last Name</label>
              <Field
                name="lastName"
                component="input"
                type="text"
                placeholder="Last Name"
                validate={required}
              />
              <Error name="lastName" />
            </div>
          </Wizard.Page>
          <Wizard.Page
            validate={values => {
              const errors = {};
              if (!values.notes) {
                errors.notes = "Required";
              }
              return errors;
            }}
          >
            <div>
              <label>Best Stooge?</label>
              <div>
                <label>
                  <Field
                    name="stooge"
                    component="input"
                    type="radio"
                    value="larry"
                  />{" "}
                  Larry
                </label>
                <label>
                  <Field
                    name="stooge"
                    component="input"
                    type="radio"
                    value="moe"
                  />{" "}
                  Moe
                </label>
                <label>
                  <Field
                    name="stooge"
                    component="input"
                    type="radio"
                    value="curly"
                  />{" "}
                  Curly
                </label>
              </div>
            </div>
            <div>
              <label>Notes</label>
              <Field name="notes" component="textarea" placeholder="Notes" />
              <Error name="notes" />
            </div>
          </Wizard.Page>
          <Wizard.Page>
            <div>
              <p>
                <b>Display all previous values here for user verification </b>
                <br />
                <i>{JSON.stringify(this.state.data, 0, 2)}</i>
              </p>
            </div>
          </Wizard.Page>
        </Wizard>
      </Styles>
    );
  }
}

render(<App />, document.getElementById("root"));

1
太好了,正是我想要的。谢谢! - Gabor Szekely

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接