React JS
React программирование @haarrp - admin @itchannels_telegram - 🔥лучшие ит-каналы @javascriptv - продвинутый javascript @programming_books_it - бесплатные it книги @ai_machinelearning_big_data - ml № 5037566384
إظهار المزيد📈 نظرة تحليلية على قناة تيليجرام React JS
تُعد قناة React JS (@react_tg) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 16 112 مشتركاً، محتلاً المرتبة 7 993 في فئة التكنولوجيات والتطبيقات والمرتبة 40 644 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 16 112 مشتركاً.
بحسب آخر البيانات بتاريخ 30 أكتوبر, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -144، وفي آخر 24 ساعة بمقدار -7، مع بقاء الوصول العام مرتفعاً.
- حالة التحقق: غير موثّقة
- معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 14.14%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 5.66% من ردود الفعل نسبةً إلى إجمالي المشتركين.
- وصول المنشورات: يحصل كل منشور على متوسط 2 279 مشاهدة. وخلال اليوم الأول يجمع عادةً 912 مشاهدة.
- التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 16.
- الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل javascript, github, css, интерфейс, браузер.
📝 الوصف وسياسة المحتوى
يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“React программирование
@haarrp - admin
@itchannels_telegram - 🔥лучшие ит-каналы
@javascriptv - продвинутый javascript
@programming_books_it - бесплатные it книги
@ai_machinelearning_big_data - ml
№ 5037566384”
بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 31 أكتوبر, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.
// до рефакторинга
async function authenticate({ user_id, token }) {
try {
const response = await axios.post('https://someapi.com/v1/auth/', {
user_id,
token,
})
console.log(response)
return response.data
} catch (error) {
console.error(error)
throw error
}
}
// после рефакторинга
async function authenticate({ user_id, jwt_token, token = jwt_token }) {
try {
const response = await axios.post('https://someapi.com/v1/auth/', {
user_id,
token,
})
console.log(response)
return response.data
} catch (error) {
console.error(error)
throw error
}
}
Сущность jwt_token будет оцениваться в тот момент, когда код дойдёт до token. В результате, если jwt_token окажется действительным токеном, и сущность token окажется равной undefined, в token попадёт значение jwt_token. Если же в token уже было какое-то значение, не являющееся по правилам JS ложным (то есть — некий реальный токен), то в token просто останется то, что там уже было.
▶️Размещайте файлы компонентов в продуманной структуре папок
Например, эта структура может выглядеть наподобие
- src
- components
- Breadcrumb
- index.js
- Breadcrumb.js
- CollapsedSeparator.js
- Input
- index.js
- Input.js
- utils.js
- focusManager.js
- Card
- index.js
- Card.js
- CardDivider.js
- Button.js
- Typography.js
📎 Читать подробнее
@react_tgnpm или yarn
1️⃣шаг: настройка структуры проекта
Создайте новую директорию для вашего проекта и перейдите к ней в вашем терминале:
mkdir react-electron-app
cd react-electron-app
mkdir -p src electron public
touch src/App.tsx src/index.tsx electron/main.ts
touch public/index.html
Теперь ваш проект должен иметь следующую структуру:
react-electron-app
├── electron
│ └── main.ts
├── public
│ └── index.html
└── src
├── App.tsx
└── index.tsx
2️⃣шаг: выполните следующую команду в терминале, чтобы инициализировать проект с файлом package.json:
npm init -y
3️⃣шаг: установите необходимые зависимости для проекта:
npm install --save react react-dom typescript electron
npm install --save-dev concurrently electron-builder electron-is-dev wait-on cross-env
4️⃣шаг: настройка Typerscript
Создайте файл tsconfig.json в корне проекта:
touch tsconfig.json
Добавьте следующее содержимое в файл tsconfig.json:
{
"compilerOptions": {
"target": "ES2023",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"]
}
5️⃣шаг: настройка приложения React
Замените содержимое файла src/App.tsx следующим кодом:
function App() {
return (
<div className='App'>
<p>
Привет, мир!
</p>
</div>
);
}
export default App;
Замените содержимое файла src/index.tsx следующим кодом:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
Замените содержимое файла public/index.html следующим кодом:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Приложение React-Electron</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
6️⃣шаг: настройка основного процесса Electron
Замените содержимое файла electron/main.ts следующим кодом:
import { app, BrowserWindow } from 'electron';
import * as path from 'path';
import * as isDev from 'electron-is-dev';
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
});
win.loadURL(
isDev
? 'http://localhost:3000'
: `file://${path.join(__dirname, '../build/index.html')}`
);
win.webContents.openDevTools();
}
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
7️⃣шаг: настройка скриптов в package.json
Откройте файл package.json и добавьте следующие скрипты в раздел “scripts”:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"eject": "react-scripts eject",
"electron:dev": "concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://127.0.0.1:3000 && tsc -p electron -w\" \"wait-on http://127.0.0.1:3000 && tsc -p electron && electron .\"",
"electron:build": "yarn build && tsc -p electron && electron-builder",
"electron:dist": "yarn build && tsc -p electron && electron-builder --mac --dir"
}
8️⃣шаг: Теперь вы можете запустить свое приложение React-Electron, выполнив следующую команду:
npm run electron:dev
Победа!
@react_tgNavbar с помощью пропса showTitle:
Плохо
return (
<Navbar showTitle={true} />
);
Хорошо
return( <Navbar showTitle /> );*️⃣Используйте тернарные операторы Отличный способ для выбора между двумя компонентами по некоторому условию Плохо
const { role } = user;
if(role === ADMIN) {
return <AdminUser />
}else{
return <NormalUser />
}
Хорошо
const { role } = user;
return role === ADMIN ? <AdminUser /> : <NormalUser />
*️⃣Используйте преимущества объектных литералов
Если у вас выбор между тремя и более компонентами, литералы объектов могут сделать код более читаемым – используйте их вместо сложных условий.
Плохо
const {role} = user
switch(role){
case ADMIN:
return <AdminUser />
case EMPLOYEE:
return <EmployeeUser />
case USER:
return <NormalUser />
}
Хорошо
const {role} = user
const components = {
ADMIN: AdminUser,
EMPLOYEE: EmployeeUser,
USER: NormalUser
};
const Component = components[role];
return <Component />;
*️⃣Используйте фрагменты
Нет никакого преимущества в использовании div вместо Fragment. Зачем нам лишний элемент в DOM?
Плохо
return (
<div>
<Component1 />
<Component2 />
<Component3 />
</div>
)
Хорошо
return (
<>
<Component1 />
<Component2 />
<Component3 />
</>
)
*️⃣Не определяйте функцию внутри рендера
Лучше не смешивать логику и рендер внутри компонента.
Плохо
return (
<button onClick={() => dispatch(ACTION_TO_SEND_DATA)}> // NOTICE HERE
This is a bad example
</button>
)
Хорошо
const submitData = () => dispatch(ACTION_TO_SEND_DATA)
return (
<button onClick={submitData}>
This is a good example
</button>
)
📎 Ещё больше полезных советов
@react_tgReact используйте управляемые компоненты. Привяжите значение поля к состоянию с помощью атрибута value и обновляйте его при помощи обработчика события onChange. Принцип работы приведен ниже:
class InputComponent extends React.Component {
state = { value: '' };
handleValueChange = (event) => this.setState({ value: event.target.value });
render() {
// Заметьте взаимодействие состояния и поля ввода — вот так все и работает!
return <input value={this.state.value} onChange={this.handleValueChange} />;
}
}
В этом коде создается текстовое поле ввода, значение которого привязано к состоянию компонента.
@react_tgclassList, который содержит удобные методы для добавления и удаления классов. В React из коробки нет никаких удобств. Свойство className — это всего лишь строка, а строки неудобны для обработки:
class Button extends React.Component {
render () {
const { isPressed, isHovered, label } = this.props;
let btnClass = 'btn';
if (isPressed) {
// Приходится конкатенировать классы
btnClass += ' btn-pressed';
} else if (isHovered) {
btnClass += ' btn-over';
}
return <button className={btnClass}>{label}</button>;
}
};
Для решения этой задачи создатели React рекомендуют использовать пакет 'classnames'. Принцип его работы прост. Вместо манипулирования строчкой напрямую, мы формируем правильный объект, который уже будет преобразован в строку:
import cn from 'classnames';
class Button extends React.Component {
render () {
const { isPressed, isHovered, label } = this.props;
// Значение — это `true` или `false`
// При значении `true` класс включен, при `false` — выключен
// `'btn'` — это класс, который будет подставлен в любом случае
const btnClass = cn('btn', {
'btn-pressed': isPressed,
'btn-over': !isPressed && isHovered,
});
return <button className={btnClass}>{label}</button>;
}
};
Подставим конкретные значения:
const btnClass = cn('btn', {
'btn-pressed': false,
'btn-over': true,
});
console.log(btnClass); // 'btn btn-over'
Функция cn() принимает на вход любое количество аргументов. Если аргумент имеет строковой тип, то он считается обязательным классом. Если это объект, тогда работает логика, описанная выше:
const btnClass = cn('btn', 'another-class', {
'btn-pressed': isPressed,
'btn-over': !isPressed && isHovered,
});
@react_tgTry-Catch с Async/Await
— надежное решение для обработки ошибок в асинхронном коде. Инкапсулируя асинхронные операции внутри try блока, разработчики получают возможность корректно перехватывать и обрабатывать ошибки, которые могут возникнуть во время выполнения.
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching data:', error);
throw error; // Re-throw the error to propagate it further
}
}
здесь try-catch блок обрабатывает наш асинхронный код, что позволяет нам фиксировать и регистрировать ошибки, возникающие во время выборки данных. Повторно выдавая ошибку, мы гарантируем ее распространение дальше по стеку вызовов, что облегчает комплексную обработку ошибок во всем приложении.
🔵Promise.catch()
Promise.catch() метод служит надежным защитником от асинхронных ошибок, предлагая краткое решение для обработки отклонений. Добавляя предложение .catch() в нашу цепочку обещаний, разработчики могут перехватывать и обрабатывать ошибки, возникающие во время выполнения асинхронных операций.
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((data) => {
// Process the data
})
.catch((error) => {
console.error('Error fetching data:', error);
// Display a user-friendly error message
alert('An error occurred while fetching data.');
});
здесь .catch() перехватывает любые ошибки, возникающие во время обработки данных, позволяя разработчикам регистрировать ошибки в целях отладки и предоставлять пользователям понятное сообщение.
В общем, обработка ошибок, особенно асинхронных, в приложениях React требует многогранного подхода.
🔤А какой вариант обработки ошибок близок именно вам? Было бы интересно услышать
@react_tgfunction useFetch(url) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then((res) => res.json())
.then((respData) => setData(respData));
}, []);
return data;
}
В этом коде не хватает зависимости. Если url изменится, то запроса данных не произойдет.
Дальше код может стать таким:
function useFetch(url) {
const [data, setData] = useState(null);
useEffect(() => {
setData(null); // не забыть сбросить данные перед загрузкой
fetch(url)
.then((res) => res.json())
.then((respData) => setData(respData));
}, [url]); // <-- не забыть зависимость
return data;
}
На этом этапе можно остановиться, и подумать, как улучшить этот hook.
Пропустим ещё несколько итераций, и финальный код, который можно считать неплохим решением, выглядит так:
function useFetch(url) {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
// флаг отмены
let cancelled = false;
setIsLoading(true);
setData(null);
setError(null);
fetch(url)
.then((res) => res.json())
.then((respData) => {
if (!cancelled) setData(respData);
})
.catch((e) => {
if (!cancelled) setError(e);
})
.finally(() => {
if (!cancelled) setIsLoading(false);
});
return () => {
// выставим признак того, что запрос отменен
cancelled = true;
};
}, [url]);
return [data, isLoading, error];
}
Эта задачка позволяет проверить понимание устройства рендеринга React, как устроено хранение состояния, когда происходят перерисовки, как заставить компонент перерисоваться в ответ на асинхронное событие, как устроена "очистка (cleanup) эффекта", как работают сайд-эффекты.
@react_tg