Форма реагирования, контролируемая магазином Flux (передовой опыт?)

Итак, у меня есть большой компонент, который будет моей формой:

<form>
 <FirstComponent value={this.state.firstValue}/>
 <SecondComponent value={this.state.secondValue}/>
 {more components here}
 <input type="submit" ... />
</form>

Этот компонент формы прослушивает магазин, который обновляет свои значения, используя firstAction, secondAction, так далее.

Примечание. Компонент обновляет свое состояние на основе store.getState(), который возвращает {firstValue: something, secondValue: something, etc}

Так скажем, мой FirstComponentэто вход:

<input type="text" value={this.props.value} 
   onChange={(e)=>this.props.firstAction(e.target.value)}
</input>

Ок, так onChange увольняет опору firstAction на самом деле это действие Flux, которое обновит мой магазин и сделает форму для повторного рендеринга. У меня есть две хорошие вещи: когда пользователь отправляет форму, я могу проверить значение FirstComponent в своем магазине и также контролировать все свое состояние из родительского компонента.

Тем не менее, это onChange Функция обратного вызова будет вызывать действие каждый раз, когда пользователь вводит один символ (поэтому он может производить много вызовов, следовательно, повторно отображает) <- может ли это вызвать серьезные проблемы с производительностью?

Вместо этого я мог бы использовать ссылки и когда пользователь нажимает кнопку отправки, получить this.refs.myFirstComponent.state... и у меня тоже будет значение (это будет неконтролируемый компонент?) Но это не похоже на рекомендацию сообщества.

Итак, мой вопрос, является ли первый подход, который я описал выше, хорошим вариантом? Как я могу оптимизировать это? Таким образом, повторная визуализация, которая должна влиять только на FirstComponent, не приводит к повторной визуализации SecondComponent и так далее? Является shouldComponentUpdateединственный путь сюда?


Изменить 1:

При первом подходе я столкнулся с проблемой... У меня есть тест e2e с использованием WebdriverIO, который добавляет значение в текстовое поле: http://webdriver.io/api/action/setValue.html

Я не знаю почему, но если я пытаюсь добавить слово "Тестирование" во входную информацию, веб-драйвер добавит только последнюю букву. Эта проблема исчезла, если вообще не использовать state / store. Тем не менее, если у меня есть государство внутри моей FirstComponent, что-то вроде:

<input type="text" value={this.state.value} 
   onChange={(e)=>this.setState({firstValue: e.target.value})}
   onBlur={()=>this.props.callback(this.state.firstValue)}
</input>

В этом случае кажется, что компонент реагирует быстрее при наборе текста (отображается только сам), а затем, когда пользователь удаляет фокус, он обновляет хранилище. Я должен сказать, что мне не нравится этот подход, потому что он не следует шаблону поднятия вашего состояния (и я чувствую, что дублирую это состояние), НО, похоже, он работает быстрее и важнее: мой тест e2e работает. Есть еще идеи?

1 ответ

Ваш первый подход (т.е. onChange действие fires flux, которое обновляет магазин и заставляет вашу форму перерисовываться), похоже, хороший путь. Я использовал это таким образом, и я видел других людей, использующих это также.

Что касается вашего следующего комментария:

Однако этот обратный вызов onChange будет вызывать действие каждый раз, когда пользователь вводит один символ (так что он может произвести много вызовов, следовательно, повторно отображает) <- может ли это вызвать серьезные проблемы с производительностью?

Да, я верю в это. Однажды я создал компонент, который содержит много других компонентов, а также некоторые поля ввода. Всякий раз, когда я вводил символ в поле ввода, весь компонент (вместе с другими компонентами, в которые он входит, и поля ввода) перерисовывался, вызывая проблему с производительностью. Это было заметно, если бы я печатал быстро. Вы можете проверить это, используя https://facebook.github.io/react/docs/perf.html.

Во всяком случае, как я обошел проблему, как вы уже сказали, путем реализации shouldComponentUpdate(),

Небольшой совет, который я хотел бы упомянуть, это создание кастома <Input /> компонент, который оборачивается <input /> и внедрение shouldComponentUpdate() (т.е. this.props.value !== nextProps.value || this.props.checked !== nextProps.checked) Таким образом, если вы создаете компонент формы, например, со многими полями ввода (используя пользовательские <Input />), только измененное поле ввода будет перерисовано.

Хотелось бы посмотреть, как другие люди тоже подходят к этой проблеме.

Другие вопросы по тегам