【问题标题】:NextJS and Formik: Conditional / Dynamic rendering form fields on select dropdownNextJS 和 Formik:选择下拉菜单上的条件/动态呈现表单字段
【发布时间】:2020-07-12 11:47:55
【问题描述】:

我在网页上使用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!
    }
];

我的页面上需要一个网络表单(组件)(基于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 =&gt; 在我的表单中一次性渲染它们。我只想查看表单中需要的那些字段,只有在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,因为在这种情况下我有一个渲染错误,因为&lt;TextField&gt; 有像onChange={handleChange} 这样声明的属性/ 仅在 Formik 表单内定义,但不在页面外。

【问题讨论】:

    标签: javascript reactjs forms next.js formik


    【解决方案1】:

    我在这里发现了一个相关的问题,在 Formik 的 Github Issue #751this article。所以我找到了一些不同但相关的解决方案。

    这里是snippet @CodeSandboxStackOverflow answer

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

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

    【讨论】:

      猜你喜欢
      • 2011-08-25
      • 2017-05-29
      • 2015-03-28
      • 1970-01-01
      • 1970-01-01
      • 2018-02-16
      • 1970-01-01
      • 2018-10-05
      • 2012-10-25
      相关资源
      最近更新 更多