When I work with JSX files Emacs automatically switches to js-jsx-mode and acts sluggishly. When I switch it to rjsx-mode it works much faster. So the idea is to override one mode with another, so that rjsx-mode is used instead of js-jsx-mode.

What is the best way to achieve this effect?

  • See the variable auto-mode-alist. – NickD Dec 31 '20 at 23:21
  • @NickD thanks but this not quite solve an issue. auto-mode-alist binds certain file extensions to certain major modes but in case of JS, JSX and JS files often use the same ".js" extension. I look for smarter solution, that will not only figure out the file is JS file but JSX in particular, as js-jsx-mode does in some way. – farynaio Jan 1 at 14:02

Starting from Emacs 27.1, this will depend on whether or not you want C-hv js-jsx-detect-syntax to be taken into account.

When that option is enabled, the default js-mode will inspect the syntax of Javascript files with a plain .js filename extension and decide whether or not to enable JSX support.

When that option is NOT enabled (or if you are using Emacs 26), the decision is purely based on whether or not the filename has a .jsx extension.

If your JSX files will always have the .jsx extension, then you could do this:

;; Use `rjsx-mode' for .jsx files.
;; `auto-mode-alist' is already taken care of if you've
;; installed `rjsx-mode' as a package.
;; (add-to-list 'auto-mode-alist '("\\.jsx\\'" . rjsx-mode))
;; Never check for JSX syntax in regular .js files.
(setq js-jsx-detect-syntax nil)

If there's a chance that the syntax checking is needed, then integrating the two turns out to be a little fiddly, on account of js-mode still being an ancestor of rjsx-mode. Try the following config:

;; Use `rjsx-mode' for JSX files.
;; `auto-mode-alist' is already taken care of if you've
;; installed `rjsx-mode' as a package.
;; (add-to-list 'auto-mode-alist '("\\.jsx\\'" . rjsx-mode))
(advice-add 'js-jsx-enable :override #'my-js-jsx-enable)
(defun my-js-jsx-enable ()
  "Use `rjsx-mode' instead of `js-jsx-mode'."
  (cl-letf (((symbol-function 'js-jsx--detect-and-enable) (lambda () t)))
;; Prevent the `rjsx-mode' ancestor `js-mode' from continuing to check
;; for JSX code.
(add-hook 'rjsx-mode-hook (lambda ()
                            (remove-hook 'after-change-functions
                                         #'js-jsx--detect-after-change t)))

You might check the issue queue for rjsx-mode, and open a new issue if necessary, so that this sort of thing could be addressed by default.

Note that in Emacs 27.1 the actual minor mode js-jsx-mode is just one of multiple possible ways for js-jsx-enable to be called, and consequently there's no benefit to targeting this mode specifically. This was different in earlier versions of Emacs, however it looks as if (a) js-jsx-mode didn't do very much before Emacs 27.1, and (b) it was only triggered for .jsx filenames (which we've already accounted for); so regardless of which Emacs version you're using, I don't believe there's any benefit to messing with js-jsx-mode itself.

  • (advice-add 'js-jsx-mode :override #'rjsx-mode) looks very interesting, I will test it in battle. Thanks! – farynaio Jan 1 at 14:07
  • I tried it but I get an error File mode specification error: (error Lisp nesting exceeds ‘max-lisp-eval-depth’) when opening js file. So it end up in fundamental mode. – farynaio Jan 1 at 21:46
  • I've now looked at rsjx-mode and I see that it derives from js-mode, meaning that my initial suggestion introduced some infinite recursion. Try it now. I've changed the approach to supporting the syntax checking feature in 27.1, and also fixed a dumb typo (extra parens) in the auto-mode-alist code (but also commented that line out, because rsjx-mode.el already updates auto-mode-alist, so you shouldn't need to do that. – phils Jan 2 at 0:40
  • Thanks @phils , meanwhile I switched entirely to rjsx for every JS matters - it seams faster. Will see how it handle everything, and in case of problems I will try your solution. – farynaio Jan 2 at 15:43
  • You could also consider using js2-mode for regular JS (you already have it -- rjsx-mode builds on top of it). I've no idea whether there are advantages to doing that, or if in practice it's fine to use rjsx-mode for everything. (My answer is very specific to the standard js-mode implementation though.) – phils Jan 2 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.