Autocompleting JSX In WebStorm
Tags: ide, react, javascript, jsx
Published: 2020-12-22 21:16:42

Today I solved a nagging problem I've had in WebStorm for months and I figured that I'd throw it up here because it might help someone else.

WebStorm, like any modern IDE, is usually pretty impressive with its code completions.  But since I switched over to more function-based components, I've experienced problems getting proper code completions when I'm adding component references in a block of JSX.  Here's a tangible example of just one component that was giving me problems:

```javascript
import * as PropTypes from 'prop-types';
import React from 'react';
import translate from '../functions/translate';

export default function TranslatedSpan(props) {
   return <span id={props.id} style={props.style}>{translate(props.english, props.replacements, props.translateTo)}</span>;
};

TranslatedSpan.propTypes = {
   english: PropTypes.string.isRequired,
   id: PropTypes.string,
   replacements: PropTypes.object,
   translateTo: PropTypes.string,
   style: PropTypes.object,
};
TranslatedSpan.defaultProps = {
   replacements: {},
   style: {},
   translateTo: '',
};
```

Nothing too fancy here.  Just a small little wrapper component that accepts a handful of props and returns a specially-formatted `<span>`.  You can see that I'm using the well-established pattern of `prop-types` to define the types of props, their default values, and whether they're required.  

The problem came when I tried to invoke this component somewhere else.  WebStorm's autocomplete had no problem "finding" the `<TranslatedSpan>` component and auto-importing it at the top of the page.  But for some reason, it was not doing anything to autocomplete the component's props.  It looked something like this:

```javascript
import React from 'react';

export default function Header() {
  return (
    <h1>
      <TranslatedSpan  {/* this is where I'd be typing */}
    </h1>
  );
}
```

When I typed "Translated", WebStorm pulled up `<TranslatedSpan>` as an available component and autoimported it.  But after the import, WebStorm did nothing else to "help" me complete the JSX for this component.  

The `english` prop is _required_.  But WebStorm was not auto-adding the prop into the component's JSX.  When I was in the body of the `<TranslatedSpan>` tag, I could not get autocomplete to show me _any_ of the props that should be available on the component.  

If you google around for this, this seems to be a bit of a running issue with WebStorm.  But after tinkering around with it for a while, I finally figured out how to "fix" it:

```javascript
import * as PropTypes from 'prop-types';
import React from 'react';
import translate from '../functions/translate';

const TranslatedSpan = props => {
   return <span id={props.id} style={props.style}>{translate(props.english, props.replacements, props.translateTo)}</span>;
};

TranslatedSpan.propTypes = {
   english: PropTypes.string.isRequired,
   id: PropTypes.string,
   replacements: PropTypes.object,
   translateTo: PropTypes.string,
   style: PropTypes.object,
};
TranslatedSpan.defaultProps = {
   replacements: {},
   style: {},
   translateTo: '',
};

export default TranslatedSpan;
```

Once I reconfigured the component as such, WebStorm's autocomplete features worked wonderfully.  It appears that WebStorm wasn't "seeing" the prop-type directives that were configured _below_ the component.  But when I moved the `export` directive _under_ the prop-type definitions, it fixed all of the code completions.

That stupid little bug had been driving me nuts _for months_.