react-typescript
Experienced DevOps Engineer with expertise in CI/CD automation, cloud infrastructure, Kubernetes, and GitOps. Provisioned a Jenkins server on AWS EC2 for automated deployments, integrating Terraform to provision VPCs and EKS clusters. Configured a Jump Server for secure Kubernetes access and implemented ArgoCD for GitOps-driven deployments. Integrated SonarQube for static code analysis and enforced quality gates in Jenkins pipelines. Built AWS ECR repositories and automated Docker image management. Ensured security by managing secrets in Jenkins Credentials Manager and implementing IAM policies for AWS resources. Configured Kubernetes Ingress via ArgoCD and deployed MongoDB with persistence strategies. Designed multi-branch Jenkins pipelines for different environments. Installed Prometheus and Grafana for monitoring with automated alerts. Optimized costs using AWS CloudWatch and Lambda for unused resource cleanup. Ensured end-to-end automation, security, and observability.
https://youtu.be/WlxcujsvcIY?si=3EUEqcPIz_aIxIEQ
TypeScript
//// TYPESCRIPT AUTOMATICALLY ASSIGNS A TYPE WHEN YOU DEFINE A VARIABLE
let variable = "hello"; // it internally assign this variable to type string --> type is string
variable = "hi"; // we can only assign/ reassign string
let age = 18; // type is number
// age="eighteen" // give error when string is assigned , when the type is number
//// EXPLICITLY PROVIDING A TYPE
let ageWithType: number = 22;
// ageWithType ="eighteen"
ageWithType = 18;
//// BASIC TYPES
let testString: string;
testString = "hello";
let testBoolean: boolean;
testBoolean = false;
//// MULTIPLE TYPES (UNION TYPES)
let testStringOrNumber: string | number;
testStringOrNumber = 10;
testStringOrNumber = "10";
// testStringOrNumber = [] // gives error when assign to array type
//// ARRAYS
let names = ["john", "jane", "tom"]; // array of string type
// names.push(3) //gives error when we try to push No to array of string type
names.push("mike");
let numbers = [11, 22, 35]; // array of number type
// numbers.push(true)
numbers.push(92);
let testStringArray: string[];
// testStringArray = [1,2,3]
testStringArray = ["one", "two", "three"];
let testNumberArray: number[];
// testNumberArray = [true, "hi", 23]
testNumberArray = [12, 55, 23];
let testStringOrNumberArray: (string | number)[];
testStringOrNumberArray = [1, "two", 3];
//// OBJECTS
let user = {
username: "john",
age: 22,
isAdmin: false,
};
user.username = "jane";
// user.age = "eighteen"
user.age = 29;
// user.isAdmin = "no"
user.isAdmin = true;
// user.phone = "+12345678"
let userObj: {
username: string;
age: number;
isAdmin: boolean;
};
userObj = {
username: "john",
age: 23,
isAdmin: true,
// phone:"+1234567" //we cant add an extra property
};
//optional property
let userObj2: {
username: string;
age: number;
isAdmin: boolean;
phone?: string; //optional
};
userObj2 = {
username: "jane",
age: 43,
isAdmin: false,
phone: "+1234567",
};
userObj2 = {
username: "jane",
age: 43,
isAdmin: false,
};
//// ANY TYPES ( BE CAREFUL )
let testAny: any;
testAny = 12;
testAny = "Hello";
testAny = true;
testAny = [true];
testAny = {};
let testAnyArray: any[];
testAnyArray = [1, "two", false, []];
//// FUNCTIONS
// void --> cant return
let sayHi = () => {
console.log("Hi, welcome");
};
// sayHi = "hi" // we cant reassign fn to string(any other type)
// return type is string
let funcReturnString = (): string => {
console.log("hi");
return "lama dev";
};
// arg -> no , return -> no
let multiple = (num: number) => {
return num * 2;
};
// arg -> no , return -> no
let multiple2 = (num: number): number => {
return num * 2;
};
// void --> cant return
let multiple3 = (num: number): void => {
num * 2;
//Do something but don't return
};
// optional argument
let sum = (num1: number, num2: number, another?: number) => {
return num1 + num2;
};
sum(2, 3);
let func = (user: { username: string; age: number; phone?: string }) => {
console.log(user.username);
};
//// TYPE ALIASES
type UserType = {
username: string;
age: number;
phone?: string;
};
let betterFunc = (user: UserType) => {
console.log(user.username);
};
// func and betterFunc is same, betterFunc is more clean and readable
type UserType2 = {
username: string;
age: number;
phone?: string;
theme: "dark" | "light";
};
const userWithTheme: UserType2 = {
username: "john",
age: 43,
// theme:"pink"
theme: "dark",
};
//FUNCTION SIGNATURES
type myFunc = (a: number, b: string) => void;
let write: myFunc = (num, str) => {
console.log(num + " times " + str);
};
//// INTERFACES--> we can extends other interface
// Be aware no equal sign
interface IUser {
username: string;
email: string;
age: number;
}
const client: IUser = {
username: "tom",
email: "tom@gmail.com",
age: 43,
};
interface IEmployee extends IUser {
employeeId: number;
}
const emp: IEmployee = {
username: "tom",
email: "tom@gmail.com",
age: 43,
employeeId: 1,
};
//// GENERICS
interface IAuthor {
id: number;
username: string;
}
interface ICategory {
id: number;
title: string;
}
interface IPost {
id: number;
title: string;
desc: string;
extra: IAuthor[] | ICategory[];
}
interface IPostBetter<T> {
id: number;
title: string;
desc: string;
extra: T[];
}
const testMe: IPostBetter<string> = {
id: 1,
title: "post title",
desc: "post desc",
extra: ["str", "str2"],
};
interface IPostEvenBetter<T extends object> {
id: number;
title: string;
desc: string;
extra: T[]; // array of objects
}
const testMe2: IPostEvenBetter<{ id:number }> = {
id: 1,
title: "post title",
desc: "post desc",
extra: [{ id: 1 }],
};
const testMe3: IPostEvenBetter<IAuthor> = {
id: 1,
title: "post title",
desc: "post desc",
extra: [{ id: 1, username: "john" }],
};
const testMe4: IPostEvenBetter<ICategory> = {
id: 1,
title: "post title",
desc: "post desc",
extra: [{ id: 1, title: "cat" }],
};
React-typescript
adding types for Data (api call data)
// components/postList/PostList.ts
import React from "react";
import PostCard from "../postCard/PostCard";
import { PostProps } from "@/types/types";
async function getData() {
const res = await fetch("https://jsonplaceholder.typicode.com/posts");
if (!res.ok) {
throw new Error("Failed to fetch data");
}
return res.json();
}
const PostList = async () => {
const data: PostProps[] = await getData();
return (
<div className="postList">
{/* <PostCard title="post title" body="post desc" /> */}
{data.map((post) => (
<PostCard key={post.id} {...post} />
))}
</div>
);
};
export default PostList;
// components/postCard/PostCard.ts
import { PostProps } from "@/types/types";
import React from "react";
const PostCard = ({title,body}: PostProps) => {
return (
<div className="postCard">
<h1>{title}</h1>
<p>{body}</p>
</div>
);
};
export default PostCard;
// types/types.ts
export type PostProps = { id: number; title: string; body: string };
https://github1s.com/safak/typescript-tutorial/blob/main/react/src/app/1-props-example/page.tsx
component as children
react event
https://github1s.com/safak/typescript-tutorial/blob/main/react/src/app/3-event-example/page.tsx
onChange -->search
onClick --> search button, delete button
how to find the event type? -> hover on -->onChange,onClick event
useState
https://github1s.com/safak/typescript-tutorial/blob/main/react/src/app/4-usestate-example/page.tsx
useContext
https://github1s.com/safak/typescript-tutorial/blob/main/react/src/app/5-usecontext-example/page.tsx
https://github1s.com/safak/typescript-tutorial/blob/main/react/src/context/ThemeContext.tsx
useRef
https://github1s.com/safak/typescript-tutorial/blob/main/react/src/app/6-useref-example/page.tsx
generic
https://github1s.com/safak/typescript-tutorial/blob/main/react/src/components/generic/Item.tsx#L14
combined --> type and exclude
https://github1s.com/safak/typescript-tutorial/blob/main/react/src/components/exclude/Shape.tsx
1. useState:
import React, { useState } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState<number>(0); // specify type for state
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
2. useEffect:
import React, { useState, useEffect } from 'react';
const MyComponent: React.FC = () => {
const [data, setData] = useState<string[]>([]);
useEffect(() => {
// fetch data from API
fetchData().then((result: string[]) => {
setData(result);
});
}, []); // dependency array to run effect only once
return (
<ul>
{data.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
};
3. useContext:
import React, { useContext } from 'react';
import MyContext from './MyContext';
const MyComponent: React.FC = () => {
const { value } = useContext(MyContext);
return <p>Context value: {value}</p>;
};
4. useReducer:
import React, { useReducer } from 'react';
interface State {
count: number;
}
type Action = { type: 'increment' } | { type: 'decrement' };
const reducer = (state: State, action: Action): State => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
};
const MyComponent: React.FC = () => {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
</div>
);
};
5. useCallback:
import React, { useState, useCallback } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState<number>(0);
const increment = useCallback(() => {
setCount((prevCount) => prevCount + 1);
}, []);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
};
6. useMemo:
import React, { useMemo } from 'react';
const MyComponent: React.FC = () => {
const expensiveCalculation = useMemo(() => {
// Perform expensive calculation
return 10 * 20;
}, []);
return <p>Result: {expensiveCalculation}</p>;
};
7. useRef:
import React, { useRef, useEffect } from 'react';
const MyComponent: React.FC = () => {
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);
return <input ref={inputRef} />;
};
Using TypeScript with React, particularly with hooks and events, can provide a more robust and type-safe development experience. Here's a detailed guide on how to utilize TypeScript in React with hooks, handling events, and some commonly used production use cases:
1. Setting up TypeScript with React:
Install necessary dependencies:
npx create-react-app my-app --template typescript
This command creates a new React project configured with TypeScript.
2. Using TypeScript with React Hooks:
useState:
import React, { useState } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState<number>(0); // specify type for state
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
useEffect:
import React, { useState, useEffect } from 'react';
const MyComponent: React.FC = () => {
const [data, setData] = useState<string[]>([]);
useEffect(() => {
// fetch data from API
fetchData().then((result) => {
setData(result);
});
}, []); // dependency array to run effect only once
return (
<ul>
{data.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
};
Handling Events:
Basic Event Handling:
import React from 'react';
const MyComponent: React.FC = () => {
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
console.log('Button clicked');
};
return (
<div>
<button onClick={handleClick}>Click me</button>
</div>
);
};
Controlled Components:
import React, { useState } from 'react';
const MyComponent: React.FC = () => {
const [inputValue, setInputValue] = useState<string>('');
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value);
};
return (
<div>
<input type="text" value={inputValue} onChange={handleChange} />
<p>Input value: {inputValue}</p>
</div>
);
};
Common Production Use Cases:
Form Handling with Validation:
import React, { useState } from 'react';
const MyForm: React.FC = () => {
const [email, setEmail] = useState<string>('');
const [error, setError] = useState<string | null>(null);
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (!email.includes('@')) {
setError('Invalid email');
} else {
// Submit form data
}
};
return (
<form onSubmit={handleSubmit}>
<input type="text" value={email} onChange={(e) => setEmail(e.target.value)} />
<button type="submit">Submit</button>
{error && <p>{error}</p>}
</form>
);
};
Fetching Data from an API:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const MyComponent: React.FC = () => {
const [data, setData] = useState<any[]>([]);
useEffect(() => {
axios.get('https://api.example.com/data')
.then(response => {
setData(response.data);
})
.catch(error => {
console.error('Error fetching data:', error);
});
}, []);
return (
<ul>
{data.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
};