Далее JS и Formik: Conditional / Dynami c поля формы рендеринга в раскрывающемся списке выбора - PullRequest
0 голосов
/ 12 июля 2020

У меня проблема с условным рендерингом с 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
  ...

Итак, как этого добиться?

Думаю, я должен добавить 3-е поле в свой массив 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, но не за пределами страницы.

1 Ответ

0 голосов
/ 13 июля 2020

Я обнаружил соответствующую проблему здесь, в Formik's Github Issue # 751 и в этой статье . Итак, я нашел немного другое, но подходящее решение моей проблемы.

Вот на фрагмент @ CodeSandbox и StackOverflow ответ для этого.

Таким образом, решение основано на субкомпоненте исходной формы, который отображается на основе поля выбора. (Именно то, что мне было нужно).

К сожалению, я не решаю проблему дублирования кода, но хорошо структурирую код и отображает только необходимую часть формы.

...