So I've thought about this some more, and realized that this won't fix everything. There are still issues with greater-than and less-than as binary operators. Maybe a better idea is to give '{' and '}' comment syntax ('<' and '>') so that SGML ignores all the bracketed JS stuff. I've been trialing this with the following:
(defvar js-jsx-tag-syntax-table
(let ((table (make-syntax-table sgml-tag-syntax-table)))
(modify-syntax-entry ?\{ "<" table)
(modify-syntax-entry ?\} ">" table)
table))
(defun advice-js-jsx-indent-line (orig-fun)
(interactive)
(let ((sgml-tag-syntax-table js-jsx-tag-syntax-table))
(apply orig-fun nil)))
(advice-add 'js-jsx-indent-line :around 'advice-js-jsx-indent-line)
and have gotten good results so far. This works for js-mode and js2-mode. If you're both happy with this approach, I'll convert the advice into a patch for `js-jsx-indent-line' and will send along!