React Final Form:根据表单值创建条件
React Final Form: make conditions according to form values
我需要根据用户在表单第一步提示的一个值生成一定数量的字段。
由于我正在使用 "Wizard" class <Condition />
组件执行多步骤表单,因此无法正常工作。
基本上我需要访问值(从功能组件内的 class 中提取它们)以便告诉 React 它需要生成的 "pages" 的数量。
像这样:
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>
)}
为了根据用户创建的项目数生成N个页面,每个项目一个页面。
这种方法不起作用,因为它告诉我这些值未定义。
这是我的 Wizard React 组件:
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>
)
}
}
这是 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>
)
我设法通过调用 React.cloneElement()
方法解决了这个问题。
此方法需要包装 activePage 变量和静态方法“Page”,这样您就可以将属性传递给子项,所以至少我设法访问每个页面内的表单值,从而创造一些条件。
您可以在此处查看工作示例:Demo - Codesandbox
我仍然没有弄清楚如何在页面外访问这些值(在向导 Class 内,但在 Wizard.Page 方法之前,这可能是理想的方式,因为我可以按顺序创建条件生成/(或不生成)页面。
我需要根据用户在表单第一步提示的一个值生成一定数量的字段。
由于我正在使用 "Wizard" class <Condition />
组件执行多步骤表单,因此无法正常工作。
基本上我需要访问值(从功能组件内的 class 中提取它们)以便告诉 React 它需要生成的 "pages" 的数量。
像这样:
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>
)}
为了根据用户创建的项目数生成N个页面,每个项目一个页面。
这种方法不起作用,因为它告诉我这些值未定义。
这是我的 Wizard React 组件:
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>
)
}
}
这是 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>
)
我设法通过调用 React.cloneElement()
方法解决了这个问题。
此方法需要包装 activePage 变量和静态方法“Page”,这样您就可以将属性传递给子项,所以至少我设法访问每个页面内的表单值,从而创造一些条件。
您可以在此处查看工作示例:Demo - Codesandbox
我仍然没有弄清楚如何在页面外访问这些值(在向导 Class 内,但在 Wizard.Page 方法之前,这可能是理想的方式,因为我可以按顺序创建条件生成/(或不生成)页面。