简体   繁体   English

React Final Form:根据表单值制定条件

[英]React Final Form: make conditions according to form values

I need to generate a certain number of fields according to a value that the user prompts in the first step of the form.我需要根据用户在表单的第一步中提示的值生成一定数量的字段。

Since I'm doing a multi-step form with a "Wizard" class <Condition /> component doesn't work.因为我正在做一个带有“向导”类的多步骤表单<Condition />组件不起作用。

Basically I need to access to values (pull them from the class inside the functional component) in order to tell React the number of "pages" it needs to generate.基本上我需要访问值(从函数组件内的类中提取它们)以告诉 React 它需要生成的“页面”的数量。

Something like this:像这样的东西:

export default () => {(
        <Wizard
            initialValues={{ }}
            onSubmit={onSubmit}
        >
            <Wizard.Page >
                <FirstStep />
            </Wizard.Page>

        {values.items.map((item, index) => (
            <Wizard.Page key="index">
                <SecondStep stepName="item.name" key="index" />
            </Wizard.Page>
        ) )}

        </Wizard>
)}

In order to generate N pages according to the number of items the user created, one page for each item.为了根据用户创建的item个数生成N个页面,每个item一个页面。

This approach does not work because it tells me that the values are not defined.这种方法不起作用,因为它告诉我这些值没有定义。

This is my Wizard React Component:这是我的向导反应组件:

import React from 'react'
import PropTypes from 'prop-types'
import { Form } from 'react-final-form'
import arrayMutators from 'final-form-arrays'

export default class Wizard extends React.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}
               mutators={{...arrayMutators }}
           >
               {({ handleSubmit, submitting, values }) => (
                   <form onSubmit={handleSubmit}>

                       {activePage}

                       <div className="buttons centered">
                           {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>
       )
   }
}

And this is the FirstStep component (where the user inserts its first values, it generates and array of items. All I need to do is pull the values of the state in order to generate a number of pages according to the length of that first array):这是 FirstStep 组件(用户插入它的第一个值,它生成项目数组。我需要做的就是提取状态的值,以便根据第一个数组的长度生成多个页面):

export default () => (

            <FieldArray name="items">
                {({ fields }) => (
                <div className="centered-items">
                    {fields.map((name, index) => (
                        <div key={name} className="item-row">
                            <label htmlFor={`item-name-${index}`}>item: </label>
                            <Field
                                id={`item-name-${index}`}
                                name={`${name}.item`} 
                                component="input"
                                type="text"
                                placeholder="Place Item Name"
                            />
                            <button type="button" onClick={() => fields.remove(index)}>
                                Remove
                            </button>
                        </div>
                    ))}
                    <button
                        className="centered"
                        type="button"
                        onClick={() => fields.push({ tipologia: '', numero_camere: '1' })}
                    >
                        Add Item
                    </button>
                </div>
                )}
            </FieldArray>
)

I manage to solve this problem calling React.cloneElement() method.我设法通过调用React.cloneElement()方法解决了这个问题。 This method needs to wrap either activePage variable and the static method " Page ", in this way you can pass properties to children, so at least I manage to access the form values inside every page and so create some conditions.此方法需要包装activePage变量和静态方法“ Page ”,这样您就可以将属性传递给子级,因此至少我设法访问每个页面内的表单值,从而创建一些条件。

You can see a working example here: Demo - Codesandbox你可以在这里看到一个工作示例: Demo - Codesandbox

I still haven't figured out how to access this values outside the page (inside Wizard Class but before Wizard.Page method, this could be the ideal way because I can create conditions in order to generate/(or not generate) pages.我仍然没有弄清楚如何在页面外(在 Wizard Class 内但在 Wizard.Page 方法之前,这可能是理想的方法,因为我可以创建条件以生成/(或不生成)页面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM