NextJS和Formik:选择下拉菜单上的条件/动态呈现表单字段



我在网页上使用Next.jsFormik进行条件渲染时遇到问题。

所以我的页面上有一个名为commands的数组,这很容易:

const commands = [
{
value: 'launch',
display_name: 'LAUNCH ROCKET!',
},
{
value: 'delay_launch',
display_name: 'LAUNCH IN..',
},
{
....list of elements, they are not API fetched!
}
];

我的页面上需要一个web表单(组件((基于Formik(

组件如下所示:

<Container>
<Formik
initialValues={{ command: 'launch', arguments: 'test'}}
onSubmit={async (values, { setSubmitting }) => {
await setSubmitting(false);
await Router.push(`/${values.command}`);
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
/* and other goodies */
}) => (
<form onSubmit={handleSubmit} noValidate autoComplete="off">
<Grid container spacing={3} direction="row" justify="center" alignItems="center">
<Grid item xs={3}>
<TextField
name="command"
select
label="Select command"
className={classes.dropdown}
onChange={handleChange}
onBlur={handleBlur}
value={values.command}
variant="outlined"
>
{commands.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
</Grid>
{/* IF COMMAND IN SELECT DROPDPWN === LAUNCH THEN RENDER THIS*/}
{values.command === "launch" && (
<React.Fragment>
<Grid item xs={3}>
<TextField
text-field
/>
</Grid>
<Grid item xs={1}>
<Typography variant="h3" align="center" style={{textTransform: 'uppercase', margin: '0'}}>
@
</Typography>
</Grid>
<Grid item xs={3}>
<TextField
another text-field
</TextField>
</Grid>
</React.Fragment>
)}
</Grid>
</form>
)}
</Formik>
</Container>

它应该如何工作

当您在页面上选择下拉列表(以Formik的形式(时,它会呈现其他字段,这取决于选择值

问题是:

正如你所看到的,如果我继续这样写代码,它将是一样的,就像我一个接一个地写每个if语句一样。

因此,如果我的命令列表中有10+个不同的命令,它将有10+if个块。但我不需要用commands.map =>在我的形式中一次呈现所有这些。只有在dropdown中选择了正确的命令时,我才希望看到表单中需要的字段。

像这样(伪代码风格(:

IF IN MY FORM SELECTED COMMAND:
LAUNCH => THEN ADD 2 ADDITIONAL FIELDS IN THIS FORM
DELAYED LAUNCH => THEN ADD 3 ADDITIONAL FIELDS IN THIS FORM
...

那么如何做到这一点呢?

我想我应该在我的commands数组中添加第三个字段,比如:

const commands = [
{
value: 'launch',
display_name: 'LAUNCH ROCKET!',
render_code: `<React.Fragment>
<Grid item xs={3}>
<TextField
text-field
/>
</Grid>
<Grid item xs={1}>
<Typography variant="h3" align="center" style={{textTransform: 'uppercase', margin: '0'}}>
@
</Typography>
</Grid>
<Grid item xs={3}>
<TextField
another text-field
</TextField>
</Grid>
</React.Fragment>`
},
....
]

但是,如何根据确定的选定值以我的形式呈现它呢?我想应该有这样的东西:Map.get(number),但我还没有找到任何例子,更重要的是,我不知道渲染代码片段应该如何存储在数组中。如果我将其存储在string值中,可以吗?

更新时间:

我正在尝试使用render_code示例,就像上面的一个示例一样,通过:

{commands.find(x => {if (x.value === values.command) return x.rendring_code})}

但问题是,如果将JSX片段存储为string,它将变成类似于:

code: "<React.Fragment>n                <Grid item xs={3}>n 

有了所有这些用于换行和其他格式化符号的n,但我无法存储纯JSX,因为在这种情况下,我有一个呈现错误,因为<TextField>具有类似onChange={handleChange}的属性,该属性仅在Formik表单内部声明/定义,而不在页面外部声明/定义。

我在Formik的Github Issue#751和本文中发现了一个相关的问题。因此,我找到了一个不同的,但相关的解决方案,我的问题。

以下是@CodeSandbox和StackOverflow的一个片段。

因此,该解决方案是基于原始表单的子组件,该子组件是基于选择字段呈现的。(这正是我所需要的(。

不幸的是,我并没有解决重复代码的问题,而是很好地构建了代码,只呈现了表单的必要部分

最新更新