I am trying to write a simple tsx function component snippet. The snippet should look like this:
import * as React from 'react'
interface HomeProps {
$2
}
const Home: React.FC<HomeProps> = ({ $2 }) => {
return <div>Home</div>
}
export default Home
Let's focus on $2. All I want to achieve is that when user finish the interface, then we should get some processed $2 in function props. Something like this:
interface HomeProps{
age: number
name: string
}
const Home: React.FC<HomeProps> = ({ age, name }) => {
...
Here is my snippet code in JSON:
"TypeScript React Function Component with Props": {
"prefix": "trfp",
"body": [
"import * as React from 'react'",
"",
"interface ${1:${TM_FILENAME/(^.)(.*)\\..*/${1:/upcase}$2/}}Props {",
"\t$2",
"}"
"",
"const $1: React.FC<$1Props> = ({ ${2/(.*):.*/$1, /g} }) => {",
"\treturn $3",
"}",
"",
"export default $1"
],
"description": "TypeScript React Function Component with Props",
}
I want some help with this line:
"const $1: React.FC<$1Props> = ({ ${2/(.*):.*/$1, /g} }) => {",
With this line I can get the result like:
interface HomeProps{
age: number
name: string
}
const Home: React.FC<HomeProps> = ({ age,
name, }) => {
...
It takes me hours but I still can't figure it out. Can someone help?
Here is my goal:
interface HomeProps{
age: number
name: string
}
const Home: React.FC<HomeProps> = ({ age, name }) => {
...
Update
I try some conditional regex to change the line to
"const $1: React.FC<$1Props> = ({ ${2/(.*):.*(\r?\n)/$1${2:+, }/g} }) => {",
Now I can get
interface HomeProps {
key: string
val: number
}
const Index: React.FC<HomeProps> = ({ key, val: number }) => {
return
}
I also try ternary condition as described in https://code.visualstudio.com/docs/editor/userdefinedsnippets.
${2:?, :}
, which means or what I want if group 2 (next line) exists, replace it with ,
, otherwise replace with a empty string.
However I also got the wrong result:
interface HomeProps {
key: string
val: number
}
const Index: React.FC<HomeProps> = ({ key${2:?, :}val: number }) => {
return
}
It seems like I am getting close to the answer but...
Try this snippet:
"TypeScript React Function Component with Props": {
"prefix": "trfp",
"body": [
"import * as React from 'react'",
"",
"interface ${1:${TM_FILENAME/(^.)(.*)\\..*/${1:/upcase}$2/}}Props {",
"\t$2",
"}"
"",
// note double-backslashes \\?
"const $1: React.FC<$1Props> = ({ ${2/(.*?)\\??:\\s*.*(\n?)/$1${2:+, }/g} }) => {",
// this also works: [?]?
// "const $1: React.FC<$1Props> = ({ ${2/(.*?)[?]?:\\s*.*(\n?)/$1${2:+, }/g} }) => {",
"\treturn $3",
"}",
"",
"export default $1"
],
"description": "TypeScript React Function Component with Props",
}
Here is where I made changes:
${2/(.*):\\s*.*(\n?)/$1${2:+, }/g}
First, you didn't seem to be accounting for the space after the :
, so I added \\s*
to the regex (\s
must be double-escaped.
Second, you need to match (but won't use) the newline between your entries. But your last entry won't have a newline so it is optionally captured (\n?)
.
Third, that optional new line is captured in group 2. After the last entry (like your name: string
) is added and you hit Tab you do not want another ,
added to the end. That should only be added if there is another entry - in which case there would be a newline between them.
So ${2:+, }
is a conditional IF. If there is a capture group 2, add ,
. If there is no group 2, nothing is added after group 1.
I don't know if it is required but the snippet also works if there are commas after the entries, like
age: number, // space after the :, comma at end
name?:string, // no space after :, comma. Optional ? removed
true? : boolean // lots of space after :, no trailing comma