React.js 表单 - 如何在最后一页包含所有值?

React.js Form - How To Include All Values On Final Page?

因此,我使用在注册页面中使用的 React-Final-Form 构建了一个向导表单。我想弄清楚如何在最后一页上显示所有用户输入,作为用户在提交之前 double-check/verify 他们的输入的一种方式。任何帮助将不胜感激!

(P.S。-我在发布之前尝试对此进行研究,但我所能找到的只是将用户输入存储在 Redux 中并从那里访问它们,我想避免这种情况,如果有的话可能。)

这是一个示例 link,它显示了我想要做的事情 - 如果您正在尝试找出解决方案,请随时分叉并尝试一下! 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);

我已将状态添加到 parent 组件。在 child 每次提交时更改此状态。我有 JSON 字符串化 parent 组件中的状态。正如您所说,无需使用 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"));