2016-04-07 2 views
3

Я пытаюсь выяснить, «правильный» способ сделать следующий React:React: обновить значение поля на основе другого поля в динамической форме

  • У меня есть форма с двумя полями, url и title.
  • Когда значение url изменяется, я вызываю вызов API на Embedly для получения метаданных о ссылке.
  • После того как метаданные были получены, я хочу обновить поле title с результатом.

Сложность в том, что поля url и title не находятся в одном и том же компоненте. Вот основная структура вида (я использую Formsy):

<Formsy.Form onSubmit={this.submitForm} onChange={this.updateState} ref="form"> 
    {fields.map(field => <FormComponent 
    name={field.name} 
    type={field.type} 
    value={field.value} 
    />)} 
    <Button type="submit">Submit</Button> 
</Formsy.Form> 

Как вы можете видеть, образуют петли над массивом полей и вызывает общий <FormComponent/> компонент для каждого из них, которая в основном большой switch, который затем вызывает соответствующий Formsy Component на основании поля type.

Логика запроса Embedly уже работает внутри компонента для url поля, но я не уверен, если есть способ сделать то, что я хочу в то же время с помощью компонента по умолчанию Input для title?

+1

Это одна из причин я переключился на [реагировать-перевождь форма] (https://github.com/davidkpiano/react- перевождь-форма). Он поддерживает «модели» в Redux, такие как модель «веб-сайт», которая состоит из URL-адреса и названия. И все, что мне нужно сделать, это пощекотать 'onChange' или' onBlur' в поле ввода, таком как url, который отправляет действие для вызова API, и как только он возвращается, я отправляю (actions.change ('website. title ', fetchedTitle)), который автоматически изменяет ввод заголовка на указанное значение (независимо от того, где он находится), так как это управляемый вход, который подается прямо из Redux. – ffxsam

+1

Да, я начинаю думать, что я строю свой собственный, худший мини-Redux. Но, по крайней мере, это помогает мне понять, почему Redux может быть полезным;) – Sacha

ответ

0

[Edit: благодаря Дэну я смог придумать лучшего решения для шага 4 и после]

Так вот решение, которое я придумал. Я понятия не имею, если это лучший образец или нет, но по крайней мере пока это работает.

Шаг 1: добавить метод addToPrefilledValues к <Form/> компонент, который принимает свойство и добавляет его к prefilledValues объекта на состояние этого компонента.

Шаг 2: добавить addToPrefilledValues к форме компонент context так, что метод передаются на все дочерние компоненты (примечание: Я мог бы также передать его в качестве опоры, но контекст, кажется, легче передать его на компоненты внучатых) ,

Шаг 3: сделать мой <URLField/> компонент вызова addToPrefilledValues всякий раз, когда он получает новые метаданные из Embedly:

this.context.addToPrefilledValues({title: result.title, body: result.description}); 

Шаг 4[Неправильно, смотрите ниже]: в shouldComponentUpdate методе <TitleField/> компонента, следить за изменениями в контексте и обновлять значение поля (если оно пусто):

shouldComponentUpdate(nextProps, nextState, nextContext) { 

    const nextTitle = nextContext.prefilledValues && nextContext.prefilledValues.title; 
    const currentTitle = this.context.prefilledValues && this.context.prefilledValues.title; 

    if (!!nextTitle && nextTitle != currentTitle && !this.input.getValue()) { 
    this.input.setValue(nextTitle); 
    } 

    return true; 
} 

Шаг 4 (лучше): при изменении формы сохраняйте все значения формы в объекте currentValue в состоянии формы.

Шаг 5: Посмотрите на:

  1. исходное значение поля (т.е. в базе данных), как и пропускают через this.props).
  2. текущее значение, введенное в поле, как указано в this.state.currentValue.
  3. предварительно заполненное значение, генерируемое вызовом API Embedly, как указано в this.state.prefilledValue.

Укажите, какой из них правильный (т. Е. Если пользователь ничего не добавил в поле, предварительно заполните его, если нет) и передайте это дочернему компоненту поля формы.

Это достигается желаемый результат:

  • <URLField/> и <TitleField/> не должны знать о том или общаются друг с другом.
  • <Form/> не должен знать о <URLField/> или <TitleField/>.

Как @ffxsam предложил, хотя, я, вероятно, следует использовать только Redux форму ...

+1

'shouldComponentUpdate()' должен только служить подсказкой для рендеринга. Не помещайте туда побочные эффекты или логику приложений, в значительной степени гарантируется случайное разбиение в будущих версиях React. Он должен быть чистым. –

+1

Tangential Redux Form и React Redux Form - это два разных проекта, я думаю, что @ffxsam ссылался на другой. У них довольно разные API. –

Смежные вопросы