TypeScript Developer mit Fokus auf React und Next.js
Faruk Varal entwickelt moderne Webanwendungen mit TypeScript, React und Next.js.
- React und Next.js für moderne Webanwendungen
- TypeScript für typsichere, wartbare Codebasen
- Node.js APIs und Headless-CMS-Integrationen
// hooks/useLocalStorage.ts
import { useState, useEffect } from 'react'
export function useLocalStorage<T>(
key: string,
initial: T
): [T, (val: T) => void] {
const [stored, setStored] =
useState<T>(() => {
try {
const item = localStorage
.getItem(key)
return item
? JSON.parse(item)
: initial
} catch {
return initial
}
})
const setValue = (val: T) => {
try {
setStored(val)
localStorage.setItem(
key, JSON.stringify(val)
)
} catch {
console.warn('Storage error')
}
}
return [stored, setValue]
}
// utils/debounce.ts
export function debounce<T extends
(...args: unknown[]) => void>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let timer: ReturnType<
typeof setTimeout
>
return (...args) => {
clearTimeout(timer)
timer = setTimeout(
() => fn(...args), delay
)
}
}
// hooks/useLocalStorage.ts
import { useState, useEffect } from 'react'
export function useLocalStorage<T>(
key: string,
initial: T
): [T, (val: T) => void] {
const [stored, setStored] =
useState<T>(() => {
try {
const item = localStorage
.getItem(key)
return item
? JSON.parse(item)
: initial
} catch {
return initial
}
})
const setValue = (val: T) => {
try {
setStored(val)
localStorage.setItem(
key, JSON.stringify(val)
)
} catch {
console.warn('Storage error')
}
}
return [stored, setValue]
}
// utils/debounce.ts
export function debounce<T extends
(...args: unknown[]) => void>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let timer: ReturnType<
typeof setTimeout
>
return (...args) => {
clearTimeout(timer)
timer = setTimeout(
() => fn(...args), delay
)
}
}
// components/Button.tsx
import type { FC, ReactNode,
ButtonHTMLAttributes } from 'react'
type Variant =
| 'primary'
| 'secondary'
| 'ghost'
interface ButtonProps extends
ButtonHTMLAttributes<HTMLButtonElement> {
variant?: Variant
loading?: boolean
children: ReactNode
}
const Button: FC<ButtonProps> = ({
variant = 'primary',
loading = false,
children,
disabled,
...props
}) => (
<button
className={`btn btn--${variant}`}
disabled={disabled || loading}
aria-busy={loading}
{...props}
>
{loading
? <span className="spinner" />
: children}
</button>
)
export default Button
// utils/cn.ts
export function cn(
...classes: (string | undefined
| null | false)[]
): string {
return classes
.filter(Boolean)
.join(' ')
}
// components/Button.tsx
import type { FC, ReactNode,
ButtonHTMLAttributes } from 'react'
type Variant =
| 'primary'
| 'secondary'
| 'ghost'
interface ButtonProps extends
ButtonHTMLAttributes<HTMLButtonElement> {
variant?: Variant
loading?: boolean
children: ReactNode
}
const Button: FC<ButtonProps> = ({
variant = 'primary',
loading = false,
children,
disabled,
...props
}) => (
<button
className={`btn btn--${variant}`}
disabled={disabled || loading}
aria-busy={loading}
{...props}
>
{loading
? <span className="spinner" />
: children}
</button>
)
export default Button
// utils/cn.ts
export function cn(
...classes: (string | undefined
| null | false)[]
): string {
return classes
.filter(Boolean)
.join(' ')
}
// lib/fetcher.ts
export class ApiError extends Error {
constructor(
public status: number,
message: string
) { super(message) }
}
export async function fetcher<T>(
url: string,
options?: RequestInit
): Promise<T> {
const res = await fetch(url, {
headers: {
'Content-Type': 'application/json',
},
...options,
})
if (!res.ok) {
throw new ApiError(
res.status,
await res.text()
)
}
return res.json() as Promise<T>
}
// types/common.ts
export type Maybe<T> = T | null
export type Optional<T> =
T | undefined
export interface Paginated<T> {
items: T[]
total: number
page: number
pageSize: number
hasNext: boolean
}
export type SortDir =
| 'asc' | 'desc'
// lib/fetcher.ts
export class ApiError extends Error {
constructor(
public status: number,
message: string
) { super(message) }
}
export async function fetcher<T>(
url: string,
options?: RequestInit
): Promise<T> {
const res = await fetch(url, {
headers: {
'Content-Type': 'application/json',
},
...options,
})
if (!res.ok) {
throw new ApiError(
res.status,
await res.text()
)
}
return res.json() as Promise<T>
}
// types/common.ts
export type Maybe<T> = T | null
export type Optional<T> =
T | undefined
export interface Paginated<T> {
items: T[]
total: number
page: number
pageSize: number
hasNext: boolean
}
export type SortDir =
| 'asc' | 'desc'
FarukVaral
Ich entwickle produktionsreife Full Stack Anwendungen mit TypeScript, React und Next.js.
“Moderne Website, professionelles Auftreten – genau das, was wir gebraucht haben.”Elbstrom Elektrotechnik, Inhaber
