Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Actions for React #115

Open
AgentRBY opened this issue Mar 13, 2023 · 1 comment
Open

Code Actions for React #115

AgentRBY opened this issue Mar 13, 2023 · 1 comment

Comments

@AgentRBY
Copy link

AgentRBY commented Mar 13, 2023

| - activation range

Create ref

Before:

<div ref={|} />

After:

const divRef = useRef<HTMLDivElement>()

<div ref={divRef} />

Also supports custom components that contain prop ref in types

Generate handler

Before:

<div onClick={|} />

After:

const handleDivClick = useCallback((event: MouseEvent<HTMLDivElement>) => {
    
}, []);

<div onClick={handleDivClick} />

Activated when the prop starts with on*, where * is any text starting with a capital letter. Also supports custom components that contain prop on* in types. Should automatically create an array of dependencies

Wrap handler into useCallback()

Before:

<div onClick={|(e) =>| { e.preventDefault() }} />

After:

const handleDivClick =  useCallback((e: MouseEvent<HTMLDivElement>) => {
  e.preventDefault();
}, []);

<div onClick={handleDivClick} />

Activation when an arrow function is passed as an argument to a prop. Should automatically create an array of dependencies.
Maybe we should improve the Wrap into useCallback instead of adding a new Code Action.

Create (prop_name) prop

Before:

// App.tsx
<MyComponent |newUnknownProp={123}| />

// MyComponent.tsx
interface Props {
	someExistsProp: string;
}

const MyComponent: React.FC<Props> = (props) => ...

After:

// App.tsx
<MyComponent newUnknownProp={123} />

// MyComponent.tsx
interface Props {
	someExistsProp: string;
	newUnknownProp: number; // Infer type from value
}

const MyComponent: React.FC<Props> = (props) => ...

Activated when the user writes an unknown prop to a component. Should work only on components whose imports are outside of node_modules. If there is no Props interface, you need to create it. The type must be infered from the value, if there is no value, the boolean type by default.

Perhaps we need to create a setting that will control how to create types for the component:

  • Via generics (const MyComponent: React.FC<Props> = (props) => ...)
  • Via props (const MyComponent = (props: Props) => ...) (should be default, reccomended by React)

This will also be useful for Create Props interface Code Action

Infer (useState|useRef) type

Before:

const [name, setName] = |useState|();

useEffect(() => {
  setName('Agent_RBY_')
}, [])

After:

const [name, setName] = useState<string>();

useEffect(() => {
  setName('Agent_RBY_')
}, [])

Activated when useState or useRef has no type specified.
For useState: if has a default value, then it must evaluate from it (except with null, undefined and [])

Create useState variable (variable_name)

Before:

<button name={|buttonName|} />

After:

const [buttonName, setButtonName] = useState<string>();

<button name={buttonName} />

Activated when an non-existing identifier is passed as a prop. The type must be infered from the prop type

@zardoy
Copy link
Owner

zardoy commented Mar 13, 2023

Create ref

I suppose before example should contain not defined indentifier, so this is quickfix to define ref with the name (similar to Create (prop_name) prop or builtin define not defined method quickfix)

Generate handler

While Wrap handler into useCallback() will be easy to implement, this one will be much much harder I think. So the question is: why can't user write e => and then use Wrap handler into useCallback() callback? On the other hand, since this plugin is intended to work with vscode only, I guess we can find workaround here.

Wrap handler into useCallback()

I think this refactoring should should activate in following cases:

  • any position in => of function or attribute name
  • either only attribute initializer selection (the whole function) or whole attribute selection

Create (prop_name) prop

I really like this one, but I was always in need for this in the following case:

interface Props {
	someExistsProp: string;
}

const MyComponent: React.FC<Props> = (props) => {
    props.newUnknownProp
}

Though if we use recommended way to specify Props interface TypeScript will suggest Declare missing property 'newUnknownProp' quickfix. So I'm good for adding this one.

Activated when useState or useRef has no type specified.

No type and initializer for useState. Also I think it would make sense to ignore setState invokations with callbacks.

And obviously declare property and add ref or useState won't have activation ranges since they are quickfixes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants