Используя Redux-Form для поисковых фильтров, как я могу «сбросить» и повторно отправить форму? - PullRequest
0 голосов
/ 29 мая 2019

Обновление: Вот пример Pen

https://codepen.io/anon/pen/vwzGYY?editors=0011

Предисловие

Исходя из моих исследований, мне кажется, что мне нужен совершенно другой подход.Может быть, вы можете предложить один?

Контекст

Я использую Redux-форму (технически более старую версию, но рассматриваемый API кажется действительно стабильным. Мы можем сжечь этот мост, когда доберемся.), Чтобы установить некоторые«фильтры» для своего рода списка результатов поиска.

В частности, поскольку я хочу, чтобы страницы были доступны для ссылок, я также задаю содержимое формы в параметрах URL-запроса через React-Router или изначально настраиваю его при загрузке страницы с помощью аналогичного механизма.

На данный момент единственным полем является "имя_организации", текстовое поле, которое используется для установки значения параметра запроса и запуска запроса API для /endpoint?name={some_name}.

Например,

<Field
  name="organization_name"
  component="input"
  type="text"
  placeholder="Organization Name"
  value={value}
/>

Я пробовал несколько вещей, но вот недавний снимок:

Я хватаю reset, change и другиевещи из реквизита по умолчанию.Я передаю handleSubmit, как требуется.

handleSubmit работает правильно, чтобы выполнить какое-то обновление состояния, установить / передать параметры URL-запроса с помощью React Router, а затем сделать новый вызов API / отображение новых результатов!Woot!

Что я хочу / ожидаю

В долгосрочной перспективе я бы хотел кнопку «Сбросить фильтры», которая возвращает все значения фильтра к значениям по умолчанию (например, установить значение «имя» пустымstring), и повторно отправляет форму (таким образом вызывая handleSubmit).

То, что я впервые попытался реализовать, это кнопка, как таковая:

<button
  name="reset_filters_button"
  type="button"
  onClick={resetAndSubmit}
  disabled={pristine || submitting}
  >
    Clear Search
</button> 

Где resetAndSubmit определено в контейнере формы следующим образом:

const resetAndSubmit = event => {
  reset();
  handleSubmit();
};

Что на самом деле происходит ... (submit имеет приоритет над отправленными событиями?)

Используя отладчик инструментов разработчика Chrome, Я ясно вижу , что вызывается метод reset, и возвращает егоdispatch(...) событие.Однако значения формы и состояния не обновляются до того, как handleSubmit() запустится и отправит форму.

Я думаю, это может быть связано с тем, что событие отправки имеет приоритет?

Я также попробовал что-то нехорошее, например, импортировал change (опору по умолчанию для контейнера) и определил кнопку сброса следующим образом:

<button
  name="reset_filters_button"
  type="button"
  onClick={() => {
    change('organization_name', '');
    methodThatDispatchesSubmitAction();
  }}
  disabled={pristine || submitting}
>
  Clear Search
</button>

Какой (еслиЯ удаляю methodThatDispatchesSubmitAction()) работает правильно, чтобы вернуть значение поля пустым, что делает форму технически "нетронутой", а также снова.

methodThatDispatchesSubmitAction() (если это не очевидно) привязывается к родительскому элементу через dispatchToProps и передается в контейнер формы, где он использует предложение "удаленной отправки", например,

// organization_list_filter == name of the Redux-Form to submit. 
dispatch(submit('organization_list_filter')); 

TL; DR и последний вопрос:

Как правильно сбросить форму и отправить ее значения по умолчанию / пустые?

Каждый раз, когда я отправляю или напрямую вызываю Redux Form «submit», в итоге отправляется форма до очистки значений из состояния или пользовательского интерфейса. Я прошел через это с отладчиком , и он не пропускает мой вызов на reset или change.Это похоже на проблему асинхронности / гонки, но Я признаю Я точно не в своей лиге в данном конкретном случае.

Я просто прямо делаю это неправильно?

1 Ответ

0 голосов
/ 29 мая 2019

Это определенно проблема состояния гонки (или поскольку мы на самом деле не имеем дело с потоками, проблемой порядка событий).

Причина использования methodThatDispatchesSubmitAction работает, когда ваш текущий пример не работает, потому что отправленное действие имеет преимущество чтения данных непосредственно из хранилища с избыточностью.Ваш пример не читает из хранилища избыточности, он читает из переданного свойства. Да, это свойство исходит из хранилища избыточности, но проблема, с которой вы сталкиваетесь, заключается в том, что оно еще не обновлено в вашем компоненте.

Потерпи меня, так как следующий фрагмент не будет полностью точным, но этого достаточно, чтобы объяснить, что ты видишь.

Submit is clicked
    -> Reset action is dispatched
       -> Reducer receives action and returns updated state
    -> Handle submit is fired using values prop (old state data still)
Component is updated with new props from redux state

Как видите, порядок событий не позволяет обновлять состояние свойства до тех пор, пока не завершится выполнение нашего кода клика.Если вы когда-либо смотрели видео в цикле событий JS (я настоятельно рекомендую его), вы будете знать, что наш дескриптор onClick будет работать полностью, прежде чем любые другие асинхронные операции (или операции синхронизации, которые происходят после нашего клика) имеют шанск запуску.

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

const resetAndSubmit = (event) => {
  reset();
  setImmediate(() => handleSubmit());
}

Это меняет порядок событий следующим образом:

Submit is clicked
    -> Reset action is dispatched
       -> Reducer receives action and returns updated state
    -> Handle submit is queued on the event loop (not run yet)
Component is updated with new props from redux state
Event loop reaches queued code and runs is
    -> Handle submit is fired using values prop (new state data)

Надеюсь, это поможет вам понять, почему возникает проблема.Что касается решений, чтобы исправить это.Очевидно, вы можете поставить в очередь дескриптор отправки, как я показал выше.Другой вариант, который вы описали как использование отправки для отправки.Третий вариант - использовать что-то более тяжелое, например, redux-thunk или redux-sagas, которые связывают действие resetAndSubmit в одну диспетчеризацию.Хотя, честно говоря, это то же самое, что и второй вариант, просто сведенный в одну отправку.Вариант четвертый, не используйте избыточность для всех ваших данных.Очевидно, что этот четвертый вариант имеет компромиссы, но я хочу сказать, что только то, что вы используете избыточность в проекте, не означает, что каждый отдельный фрагмент данных должен быть в избыточности.Хотя это полностью противоречит цели редукс-форм.

Я также должен добавить, что вы не одиноки в этом смущении.Когда вы вводите избыточность, это мешает тому, как вы обычно думаете о работе с кодом.Обычно вы думаете, что я делаю A, а затем B. Но с редуксом вы делаете A, ждете изменений A, чтобы сделать это через систему, а затем вы делаете B. Вот где могут быть хороши Sagas или Thunks.Вы перемещаете больше логики в хранилище, чтобы воздействовать на диспетчеризацию, а не ждать, пока все вернется обратно к компоненту через реквизит.

...