Возникли проблемы при получении данных о событии из прослушивателя событий в ReasonReact
Я пытаюсь реализовать динамическое изменение размера столбца в таблице (как в Excel или Google Sheets).
В моей функции рендеринга я использую handle
обратный вызов, когда пользователь нажимает кнопку мыши на моем элементе управления изменением размера:
<div
className="resizer"
onMouseDown={self.handle(handleColumnResizeStart)}
/>
В обработчике я хочу добавить новый слушатель событий для mousemove, чтобы, когда пользователь "перетаскивает", мы могли нарисовать что-то, чтобы указать, где будет находиться новый край столбца.
В обработчике mousemove я думал, что могу послать действие редуктора, которое содержит координату clientX мыши, чтобы обновить состояние компонента, чтобы функция рендеринга могла рисовать что-то во время перетаскивания.
let handleColumnResizeStart = (evt, self) => {
/* this handler gets invoked when the mouse is moved */
let handleMouseMove = evt => {
Js.log(evt); /* in js land I can see that clientX is in that evt object */
Js.log(ReactEvent.Mouse.clientX(evt)); /* but this creates type errors */
};
/* adds an event handler using the bs-webapi module */
Webapi.Dom.EventTarget.addEventListener(
"mousemove",
handleMouseMove,
document,
);
};
Когда я пытаюсь использовать ReactEvent.Mouse.clientX(evt)
чтобы получить конкретное значение int clientX, я получаю эту ошибку:
25 Webapi.Dom.EventTarget.removeEventListener(
26 ┆ "mousemove",
27 ┆ handleMouseMove,
28 ┆ document,
29 ┆ );
This has type:
ReactEvent.Mouse.t => unit
But somewhere wanted:
Dom.event => unit
The incompatible parts:
ReactEvent.Mouse.t (defined as
ReactEvent.synthetic(ReactEvent.Mouse.tag))
vs
Dom.event (defined as Dom.event_like(Dom._baseClass))
>>>> Finish compiling(exit: 1)
Мое понимание системы типов здесь ограничено, и я не уверен, как получить значение мышиной координаты clientX в переменную.
1 ответ
Хотя события, полученные от React и от обработчиков событий, подключенных непосредственно к DOM, могут выглядеть одинаково, на самом деле они разные. React не дает вам необработанное событие DOM, но представляет собой SyntheticEvent, и поэтому в Reason им были даны разные типы, о чем и сообщает ошибка типа. Вы не можете использовать Dom.event
где ReactEvent.Mouse.t
ожидается. В этом случае evt
это Dom.event
потому что он был получен путем подключения обработчика событий непосредственно к DOM с помощью bs-webapi
, а также ReactEvent.Mouse.clientX
конечно ожидает ReactEvent.Mouse.t
,
Так что вместо использования ReactEvent.Mouse.clientX
, вы должны использовать Webapi.Dom.MouseEvent.clientX
,
К сожалению, это все еще не будет работать, потому что Webapi.Dom.MouseEvent.clientX
ожидает Dom.mouseEvent
не Dom.event
, который является супертипом всех типов событий DOM и слишком общим для использования с функциями, специфичными для событий мыши. И это в свою очередь потому, что Webapi.Dom.EventTarget.addEventLsitener
не может этого понять "mousemove"
означает, что это событие мыши. Вы должны вместо этого использовать Webapi.Dom.EventTarget.addMouseMoveEventListener
, который дает вам Dom.mouseEvent
,
Обратите внимание, что ошибка типа, которую вы получаете, вводит в заблуждение больше, чем нужно, потому что она выведет тип и укажет на то, что ошибка где-то не там, где вы чувствуете, что ошибка возникла. Рекомендуется комментировать типы, по крайней мере, когда вы получаете ошибку типа, которую вам трудно понять. Таким образом, компилятор не выведет тип как нечто, чего вы не ожидаете, и будет содержать источник ошибки.
Вы также можете использовать Webapi.Dom.Document
вместо Webapi.Dom.EventTarget
, Document
наследует все в EventTarget
, но будет документировать и ограничивать тип, с которым вы работаете.