Skip to content

Instantly share code, notes, and snippets.

@num13ru
Created January 24, 2025 21:57
Show Gist options
  • Save num13ru/4a0bdbd5b0b58cb324394f8bcf970774 to your computer and use it in GitHub Desktop.
Save num13ru/4a0bdbd5b0b58cb324394f8bcf970774 to your computer and use it in GitHub Desktop.
Interview helpers
const debounce = (fn, delay) => {
let timer;
return function (...args) {
const context = this;
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
fn.apply(context, args);
}, delay);
};
};
function deepClone(value) {
// Проверяем, является ли значение объектом (включая массивы, но исключая null)
if (value === null || typeof value !== 'object') {
return value;
}
// Если это массив, создаем новый массив и рекурсивно копируем элементы
if (Array.isArray(value)) {
return value.map(deepClone);
}
// Если это объект, создаем новый объект и копируем его свойства
const result = {};
for (const key in value) {
if (Object.prototype.hasOwnProperty.call(value, key)) {
result[key] = deepClone(value[key]);
}
}
return result;
}
//Если нужно учесть сложные типы данных, такие как Date, Set, Map, можно доработать функцию:
function deepClone(value) {
if (value === null || typeof value !== 'object') {
return value;
}
if (value instanceof Date) {
return new Date(value);
}
if (value instanceof Set) {
return new Set(Array.from(value).map(deepClone));
}
if (value instanceof Map) {
return new Map(
Array.from(value.entries()).map(([key, val]) => [deepClone(key), deepClone(val)])
);
}
if (Array.isArray(value)) {
return value.map(deepClone);
}
const result = {};
for (const key in value) {
if (Object.prototype.hasOwnProperty.call(value, key)) {
result[key] = deepClone(value[key]);
}
}
return result;
}
import { useEffect, useRef, useState } from "react";
const BASE_URL = "https://jsonplaceholder.typicode.com";
interface Post {
id: number;
title: string;
}
export const SomeComponent = () => {
const [{ items, loading, error }, setData] = useState({
items: [] as Post[],
loading: false,
error: null,
});
const [page, setPage] = useState(1);
const abortControllerRef = useRef<AbortController | null>(null);
useEffect(() => {
const fetchPosts = async () => {
abortControllerRef.current?.abort();
abortControllerRef.current = new AbortController();
setData((prev) => ({ ...prev, loading: true }));
try {
const response = await fetch(`${BASE_URL}/posts?_page=${page}`, {
signal: abortControllerRef.current?.signal,
});
if(response.ok) {
const items = (await response.json()) as Post[];
setData((prev) => ({ ...prev, items }));
}
} catch (e: any) {
if (e.name === "AbortError") {
console.log("Aborted");
return;
}
setData((prev) => ({ ...prev, error: e }));
} finally {
setData((prev) => ({ ...prev, loading: false }));
}
};
fetchPosts();
}, [page]);
if (error) {
return <div>Something went wrong! Please try again.</div>;
}
return (
<div className="tutorial">
<h1 className="mb-4 text-2xl">Data Fetching in React</h1>
<button onClick={() => setPage(page - 1)}>Decrease Page ({page})</button>
<button onClick={() => setPage(page + 1)}>Increase Page ({page})</button>
{loading && <div>Loading...</div>}
{!loading && (
<ul>
{items.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
)}
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment