A collection of common Javascript and Typescript vim snippets for developing React applications. The snippets within this repo rely on LuaSnip or UltiSnips as the snippet provider.
some-typescript-example.mov
Previewing Snippets with coc-snippets
coc-snippets-preview.mov
log-helpers.mov
test-utils.mov
{
"hrsh7th/nvim-cmp",
dependencies = {
"L3MON4D3/LuaSnip",
"saadparwaiz1/cmp_luasnip",
+ "mlaursen/vim-react-snippets",
},
---@param opts cmp.ConfigSchema
opts = function()
vim.api.nvim_set_hl(0, "CmpGhostText", { link = "Comment", default = true })
+ require("vim-react-snippets").lazy_load()
local cmp = require("cmp")
local luasnip = require("luasnip")
local compare = cmp.config.compare
With vim-plug and UltiSnips:
call plug#begin('~/.vim/plugged')
Plug 'SirVer/ultisnips'
Plug 'mlaursen/vim-react-snippets'
call plug#end()
NOTE: I no longer use UltiSnips so the snippets might be different. Check out the UltiSnips folder to see available snippets.
Most of the available snippets will be listed below to showcase the generated
code. Tabstops will be indicated with $TABSTOP
or $NAME
where $NAME
is
replaceable. $CFN
or $CFN_
will indicate a snippet that uses the current
file name to generate the code.
Some snippets support an "inline" version as where the const whatever =
will
be omitted. These snippets will be marked with ✨.
Javascript snippets are not shown since I really only use Typescript now, but they are generally the same without the type definitions included.
- Function Components
- Hooks and Effects
- Redux
- Common
- JSDoc/TSDoc
- Logging
- Importing
- Exporting
- NODE_ENV
- Tests
- React Testing
fce
->
import { type ReactElement, type ReactNode } from "react"
export interface $CFN_Props {
$TABSTOP
children: ReactNode
}
export function $CFN(props: $CFN_Props): ReactElement {
return <></>
}
fcde
->
import { type ReactElement, type ReactNode } from "react"
export interface $CFN_Props {
$TABSTOP
children: ReactNode
}
export default function $CFN(props: $CFN_Props): ReactElement {
return <></>
}
sfce
->
import { type ReactElement } from "react"
export function $CFN(): ReactElement {
return <></>
}
sfcde
->
import { type ReactElement } from "react"
export default function $CFN(): ReactElement {
return <></>
}
ffce
->
import { forwardRef, type ReactNode } from "react"
export interface $CFNProps {
$TABSTOP
children: ReactNode
}
export const $CFN = forwardRef<HTML$TABSTOPElement, $CFN_Props>(
function $CFN(props, ref) {
return <div ref={ref}></div>
}
)
ffcde
->
import { forwardRef, type ReactNode } from "react"
export interface $CFNProps {
$TABSTOP
children: ReactNode
}
export default forwardRef<HTML$TABSTOPElement, $CFN_Props>(
function $CFN(props, ref) {
return <div ref={ref}></div>
}
)
useS
->
const [$STATE, set$STATE] = useState$TABSTOP($TABSTOP)
useRed
->
const [$STATE, $DISPATCH] = useReducer(function reducer(state: $STATE, action: $ACTION): $STATE {
switch (action.type):
default:
return state
}, $INITIAL_STATE)
useE
->
useEffect(() => {
$TABSTOP
}, [])
useC
->
const context = useContext($TABSTOP)
useCB
->
const $CALLBACK = useCallback(($TABSTOP) => {
$TABSTOP
}, [])
useM
->
const $MEMOIZED = useMemo(() => ({
$TABSTOP
}), [])
useMR
->
const $MEMOIZED = useMemo(() => {
$TABSTOP
}, [])
useR
->
const $REF = useRef$TABSTOP(TABSTOP)
ccp
->
import { createContext, useContext } from "react"
export interface $CFN_Context {}
const context = createContext<$CFN_Context | null>(null)
const { Provider } = context
export function use$CFN_Context(): $CFN_Context {
const value = useContext(context)
if (!value) {
throw new Error("$CFN_Context must be initialized.")
}
return value
}
useD
->
const dispatch = useAppDispatch()
useSL
->
const $VALUE = useSelector(($STATE: AppState) => $SELECTOR)
useAS
->
const $VALUE = useAppSelector(($STATE) => $SELECTOR)
dc
->
const { $TABSTOP } = $PROPS
dcuseSomeHook()
^ trigger completion here
const { $TABSTOP } = useSomeHook()
edc
->
const { $TABSTOP } = $PROPS
if
->
if ($CONDITION) {
$TABSTOP
}
else
->
else $TABSTOP{
$TABSTOP
}
The if
snippet can be triggered from the first tabstop to generate:
else if{
$TABSTOP
}
into:
else if ($CONDITION) {
$TABSTOP
}
switch
->
switch ($KEY) {
case $VALUE:
$TABSTOP
break
default:
$TABSTOP
}
for
->
for (let $I = $0, $I < $LIST.length; $I++) {
const $ITEM = $LIST[$I]
$TABSTOP
}
reduce
->
const $VALUE = $LIST.reduce<$TYPE_DEF>(($result, $item) => {
$TABSTOP
return $RESULT
}, $INITIAL)
noop
->
const noop = (): void => {
// do nothing
}
intf
->
export interface $CFN_$TABSTOP {
$TABSTOP
}
/**
->
/**
* $TABSTOP
*/
@e
->
@example $EXAMPLE_NAME
\`\`\`$TSX
$TABSTOP
\`\`\`
@d
->
@defaultValue \`$TABSTOP\`
@s
->
@since $MAJOR.$MINOR.$PATCH
Shortcut | Nane | Expands to |
---|---|---|
cl |
Console Log | console.log($TABSTOP) |
clv |
Console Log Variable | console.log("$TABSTOP: ", $TABSTOP) |
ce |
Console Error | console.error($TABSTOP) |
cev |
Console Error Variable | console.error("$TABSTOP: ", $TABSTOP) |
cw |
Console Warn | console.warn($TABSTOP) |
cwv |
Console Warn Variable | console.warn("$TABSTOP: ", $TABSTOP) |
ct |
Console Table | console.table($TABSTOP) |
cd |
Console Debug | console.debug($TABSTOP) |
cdv |
Console Debug Variable | console.debug("$TABSTOP: ", $TABSTOP) |
Note: The logging commands that end in a
v
will have the cursor at the second$TABSTOP
instead of the first so that autocompletion will work.
Shortcut | Name | Expands to |
---|---|---|
imp |
Import | import packageName from "package-name" |
impf |
Import File | import File from "./File" |
impd |
Import Destructured | import { destructured } from "package-or/path" |
impp |
Import (Please?) | import "./file" |
icn |
Import Classnames | import cn from "classnames" |
icnb |
Import Cnbuilder | import { cnb } from "cnbuilder" |
ism |
Import Styles Module | import styles from "./$CFN.module.scss" |
Shortcut | Name | Expands to |
---|---|---|
exp |
Export | export { default } from "./$CFN" |
expf |
Export File | export $TABSTOP from "./$TABSTOP" |
expd |
Export Destructured | export { $TABSTOP } from "./$TABSTOP" |
expa |
Export All | export * from "$TABSTOP" |
Shortcut | Expands to |
---|---|
dev |
process.env.NODE_ENV !== "production" |
prod |
process.env.NODE_ENV === "production" |
desc
->
describe('$CFN', () => {
it('should $TABSTOP', () => {
$TABSTOP
)}
})
it
->
it("should $TABSTOP", () => {
$TABSTOP
})
ita
->
it("should $TABSTOP", async () => {
$TABSTOP
})
Shortcut | Name | Expands to |
---|---|---|
es |
Expect Snapshot | expect(${container}).toMatchSnapshot() |
ett |
Expect To Throw | expect(() => $TABSTOP).toThrow() |
entt |
Expect Not To Throw | expect(() => $TABSTOP).not.toThrow() |
enc |
Expect Not Called | expect($TABSTOP).not.toHaveBeenCalled() |
ecw |
Expect Called With | expect($TABSTOP).toHaveBeenCalledWith($TABSTOP) |
ect |
Expect Called Times | expect($TABSTOP).toHaveBeenCalledTimes($TABSTOP) |
Shortcut | Name | Expands to |
---|---|---|
sgbr |
Screen Get By Role | const $TABSTOP = screen.getByRole("${button}", { name: "$TABSTOP" }) |
sgbru |
Screen Get By Role (Unnamed) | const $TABSTOP = screen.getByRole("${progressbar}") |
sgbi |
Screen Get By testId | const $TABSTOP = screen.getByTestId("$TABSTOP") |
sgbt |
Screen Get By Text | const $TABSTOP = screen.getByText("$TABSTOP") |
sfbr |
Screen Find By Role | const $TABSTOP = await screen.findByRole("${button}", { name: "$TABSTOP" }) |
sfbru |
Screen Find By Role (Unnamed) | const $TABSTOP = await screen.findByRole("${progressbar}") |
fbi |
Screen Find By testId | const $TABSTOP = await screen.findByTestId("$TABSTOP") |
fbt |
Screen Find By Text | const $TABSTOP = await screen.findByText("$TABSTOP") |
gbr |
Get By Role | const $TABSTOP = getByRole("${button}", { name: "$TABSTOP" }) |
gbru |
Get By Role (Unnamed) | const $TABSTOP = getByRole("${progressbar}") |
gbi |
Get By testId | const $TABSTOP = getByTestId("$TABSTOP") |
gbt |
Get By Text | const $TABSTOP = getByText("$TABSTOP") |
fbr |
Find By Role | const $TABSTOP = await findByRole("${button}", { name: "$TABSTOP" }) |
fbru |
Find By Role (Unnamed) | const $TABSTOP = await findByRole("${progressbar}") |
fbi |
Find By testId | const $TABSTOP = await findByTestId("$TABSTOP") |
fbt |
Find By Text | const $TABSTOP = await findByText("$TABSTOP") |
rtf
->
import { render, screen, userEvent } from "${@testing-library/react}"
import { $CFN } from "../$CFN"
describe("$CFN", () => {
it("should $TABSTOP", () => {
$TABSTOP
})
})
rtfe
->
import { render, screen, userEvent } from "${@testing-library/react}"
import { $CFN } from "../$CFN.js"
describe("$CFN", () => {
it("should $TABSTOP", () => {
$TABSTOP
})
})
gtf
->
import { describe, expect, it } from "${@jest/globals}"
import { render, screen, userEvent } from "${@testing-library/react}"
import { $CFN } from "../$CFN"
describe("$CFN", () => {
it("should $TABSTOP", () => {
$TABSTOP
})
})
gtfe
->
import { describe, expect, it } from "${@jest/globals}"
import { render, screen, userEvent } from "${@testing-library/react}"
import { $CFN } from "../$CFN.js"
describe("$CFN", () => {
it("should $TABSTOP", () => {
$TABSTOP
})
})
uet
->
it("should $TABSTOP", async () => {
const user = userEvent.setup()
$TABSTOP
expect(true).toBe(true)
})
wf
->
await waitFor(() => {
$TABSTOP
})
Shortcut | Name | Expands to |
---|---|---|
use |
Use | @use "$TABSTOP"; |
use* |
Use * | @use "$TABSTOP" as *; |
for |
Forward | @forward "$TABSTOP" with ($TABSTOP); |
pcs |
Prefers Color Scheme | @media (prefers-color-scheme: $DARK) { $TABSTOP } |
local ls = require("luasnip")
local s = ls.snippet
local sn = ls.snippet_node
local isn = ls.indent_snippet_node
local t = ls.text_node
local i = ls.insert_node
local f = ls.function_node
local c = ls.choice_node
local d = ls.dynamic_node
local r = ls.restore_node
local events = require("luasnip.util.events")
local ai = require("luasnip.nodes.absolute_indexer")
local extras = require("luasnip.extras")
local l = extras.lambda
local rep = extras.rep
local p = extras.partial
local m = extras.match
local n = extras.nonempty
local dl = extras.dynamic_lambda
local fmt = require("luasnip.extras.fmt").fmt
local fmta = require("luasnip.extras.fmt").fmta
local conds = require("luasnip.extras.expand_conditions")
local postfix = require("luasnip.extras.postfix").postfix
local types = require("luasnip.util.types")
local parse = require("luasnip.util.parser").parse_snippet
local ms = ls.multi_snippet
local k = require("luasnip.nodes.key_indexer").new_key