martinheidegger / react-typescript-presentation

Presentation abut using typescript with react.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

theme transition
white
slide

React & TypeScript

Tipps & Tricks


Why?

(... am I standing in front of you?)

  • TypeScript is a common topic ✨
  • React is very popular πŸ€·β€β™‚οΈ
  • Many ways, choices and problems 😳

Today

  • Start with a simple project πŸ”°
  • Look at a few common concepts
  • Improve little by little πŸš€
  • Learn along the way πŸ§‘β€πŸŽ“

Typedy Typedy

Choose your level of typescript.

  1. Just make your life easier
  2. Make team life easier
  3. Make code safer
  4. Typed all the way

Just make your life easier

Get more docs.

$ npm install \
          @types/react \
          @types/react-dom \
          --save-dev

Mixing tsx & jsx


Use .d.ts

Use .jsx with .tsx


Easy renaming

No: "export default"


Stuck at the basics

  • import React from 'react'
  • import * as React from 'react'
  • tsconfig.json
    {
      "compilerOptions": {
        "jsx": "react-jsx"
      }
    }

More tsconfig shenanigans


tsconfig.json

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "target": "ES2020",
    "lib": ["DOM", "ES2020"]
  }
}

tsconfig.json

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "target": "ES2020",
    "lib": ["DOM", "ES2020"],
    "moduleResolution": "NodeNext"
  }
}

Props LVL 1

define the props

export const Main = ({ value }: { value: string }) =>
  <div className="main">{value}</div>

Props LVL 2

extract to an interface

interface MainProps {
  value: string
}
export const Main = ({ value }: MainProps) => 
  <div className="main">{value}</div>

Props LVL 3

export it!

export interface MainProps {
  value: string
}
export const Main = ({ value }: MainProps) => 
  <div className="main">{value}</div>

Props LVL 4

Is it optional? Make it optional!

interface MainProps {
  value?: string
}
export const Main = ({ value }: MainProps) => 
  <div className="main">{value}</div>

Props LVL 5

Pass other properties as well!

type DivProps = React.DetailedHTMLProps<
  React.HTMLAttributes<HTMLDivElement>,
  HTMLDivElement,
>;

export interface MainProps extends DivProps {
  value?: string
}
export const Main = (props: MainProps) => {
  const { value, ...rest } = props
  return <div className="main" {...rest}>{value}<div>
}

Props LVL 6

merge instead of override

$ npm install classnames --save

Props LVL 6 (2)

components/Main.tsx

import classNames from 'classnames'

type DivProps = React.DetailedHTMLProps<
  React.HTMLAttributes<HTMLDivElement>,
  HTMLDivElement,
>;

export interface MainProps extends DivProps {
  value?: string
}
export const Main = (props: MainProps) => {
  const { value, className, ...rest } = props
  return <div
    className={classNames('main', className)}
    {...rest}
  >{value}<div>
}

Props LVL 7

import { forwardRef } from 'react'

export const Main = forwardRef((props: MainProps, ref) => {
  const { value, className, ...rest}
  return <div
    ref={ref}
    className={classNames('main', className)}
    {...rest}
  >{value}</div>
})

Props LVL 7 (2)

import { forwardRef } from 'react'

export const Main = forwardRef<HTMLDivElement>(
  (props: MainProps, ref) => {
    const { value, className, ...rest}
    return <div
      ref={ref}
      className={classNames('main', className)}
      {...rest}
    >{value}</div>
  }
)

Child LVL 1

export interface MainProps {
  children: string
}
export const Main = ({ children }: MainProps) => {
  return <div className='main'>{children}<div>
}

Child LVL 2

export interface MainProps {
  children: string | string[]
}
export const Main = ({ children }: MainProps) => {
  return <div className='main'>{children}<div>
}

Child LVL 3

types.d.ts

export type OneOrMany <T> = T | T[]

component/Main.tsx

import type { OneOrMany } from '../types.d.ts'

export interface MainProps {
  children: OneOrMany<string>
}
export const Main = ({ children }: MainProps) => {
  return <div className='main'>{children}<div>
}

Child LVL 4

types.d.ts

export type OneOrMany <T> = T | T[]

component/Main.tsx

import type { OneOrMany } from '../types.d.ts'
import { Children } from 'react'

export interface MainProps {
  children: OneOrMany<string>
}
export const Main = ({ children }: MainProps) => {
  return <div className='main'>{
    Children(children).join('')
  }<div>
}

Team: keep TS version

$ npm install \
          typescript \
          --save-dev

Use TS version in VSCode

Easy to miss!

  • (in ts file) Cmd + P
  • "> TypeScript: Select TypeScript Version..."
  • "Use Workspace Version"

TS Version in settings

.vscode/settings.json

{
  "typescript.tsdk": "./node_modules/typescript/lib"
}

Team: use linting

😜


Type your data

interface Project {
  id: string,
  name: string,
  data: any,
}

export const ProjectDisplay = ({ project }: ProjectDisplayProps) => {
  return <div className="project-display">
  
  </div>
}

Type what you Receive!

(bad, but a good start)

import { useEffect, useState } from 'react'

export const Events = () => {
  const [state, setState] = useState<any>()
  useEffect(
    () => {
      fetch('https://owddm.com/public/events.json')
        .then(res => res.json())
        .then(data => setState({
          data,
          success: true
        }))
    },
    []
  )
  return <></>
}

Make our life easier

  • npm i swr

Make our life easier (2)

util/fetchJSON.ts

async function fetchJSON(url: string) {
  return await (await fetch(url)).json()
}

component/Events.tsx

import useSWR from 'swr'

export const Events = () => {
  const data = useSWR(
    'https://owddm.com/public/events.json',
    async url => await fetchJSON(url)
  )
  return <ul className="events">{
    data.data?.venues.map(venue => 
      <li key={venue.id}>{venue.name}</li>
    )
  }</ul>
}

Make our life easier (2)

util/fetchJSON.ts

async function fetchJSON(url: string) {
  return await (await fetch(url)).json()
}

component/Events.tsx

import useSWR from 'swr'

export const Events = () => {
  const data = useSWR(
    'https://owddm.com/public/events.json',
    async url => await fetchJSON(url)
  )
  return <ul className="events">{
    data.data?.venues.map(venue => 
      <li key={venue.id}>{venue.name}</li>
    )
  }</ul>
}

About

Presentation abut using typescript with react.


Languages

Language:TypeScript 77.7%Language:JavaScript 22.3%