【发布时间】:2020-07-12 11:47:55
【问题描述】:
我在网页上使用Next.js 和Formik 进行条件渲染时遇到问题。
所以我的页面上有一个名为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 => 在我的表单中一次性渲染它们。我只想查看表单中需要的那些字段,只有在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 表单内定义,但不在页面外。
【问题讨论】:
标签: javascript reactjs forms next.js formik