Type Guards (захист типів) - це функціональність у TypeScript, яка дозволяє перевіряти тип змінної або виразу під час виконання програми. Це особливо корисно, коли робота з різними типами даних у різних умовах та функціях може призвести до помилок компіляції або помилок виконання.
TypeScript надає кілька способів Type Guards:
1. typeof: оператор typeof дозволяє перевірити тип змінної під час виконання. Наприклад:
#tsquestions
TypeScript надає кілька способів Type Guards:
1. typeof: оператор typeof дозволяє перевірити тип змінної під час виконання. Наприклад:
function isString(input: string | number): input is string {
return typeof input === "string";
}
const value: string | number = "Hello";
if (isString(value)) {
console.log(value.toUpperCase());
}
2. instanceof: оператор instanceof перевіряє, чи є об'єкт екземпляром певного класу. Наприклад:class Person {
name: string;
age: number;
}
class Employee extends Person {
id: number;
position: string;
}
function isEmployee(input: Person): input is Employee {
return input instanceof Employee;
}
const person: Person = new Employee();
if (isEmployee(person)) {
console.log(person.id);
}
3. in: оператор in перевіряє, чи є певна властивість в об'єкті. Наприклад:interface Circle {
radius: number;
}
interface Square {
side: number;
}
function isCircle(shape: Circle | Square): shape is Circle {
return "radius" in shape;
}
const shape: Circle | Square = { radius: 5 };
if (isCircle(shape)) {
console.log(shape.radius);
}
Type Guards дозволяють писати безпечніший код, що запобігає помилкам під час виконання програми, пов'язані з неправильним використанням типів даних.#tsquestions
Type Casting (приведення типів) - це функціональність у TypeScript, яка дозволяє явно вказувати компілятору, який тип повинен використовуватися для змінної або виразу у певному контексті.
У TypeScript є два види приведення типів:
1. Angle-bracket Syntax (синтаксис кутових дужок): Цей спосіб полягає у використанні кутових дужок <> та вказівці потрібного типу всередині них. Наприклад:
Приведення типів часто використовується для роботи з типами даних, які не збігаються з типом змінної або параметром функції, наприклад, для роботи з DOM-елементами або об'єктами API. Однак при використанні типів слід бути обережним, оскільки неправильне використання може призвести до помилок виконання програми.
react:
OR
#tsquestions
У TypeScript є два види приведення типів:
1. Angle-bracket Syntax (синтаксис кутових дужок): Цей спосіб полягає у використанні кутових дужок <> та вказівці потрібного типу всередині них. Наприклад:
const myVariable: any = "123";2. as Syntax (синтаксис as): Цей спосіб полягає у використанні оператора as для приведення типів. Наприклад:
const stringLength = (<string>myVariable).length;
const myVariable: any = "123";Обидва способи приведення типів мають свої переваги та недоліки, але в цілому як syntax більш читабельний і має ширшу підтримку в мові.
const stringLength = (myVariable as string).length;
Приведення типів часто використовується для роботи з типами даних, які не збігаються з типом змінної або параметром функції, наприклад, для роботи з DOM-елементами або об'єктами API. Однак при використанні типів слід бути обережним, оскільки неправильне використання може призвести до помилок виконання програми.
react:
const input = document.getElementById('inputEmail') as HTMLInputElement;
input.value = 'test@test.ts';OR
const input = document.getElementById('inputEmail');
if (input) {
(input as HTMLInputElement).value = 'test@test.ts';
}#tsquestions
Index Properties(властивості-індекси) - це функціональність в TypeScript, яка дозволяє створювати об'єкти з властивостями, що динамічно задаються.
Об'єкти TypeScript можуть мати лише певні властивості, які були оголошені заздалегідь. Однак, при роботі з деякими API або даними, може виникнути необхідність динамічно створюваних властивостей, які не відомі заздалегідь. У цьому випадку можуть допомогти Index Properties.
Для створення Index Properties використовується наступний синтаксис:
У цьому прикладі ми оголошуємо інтерфейс MyObject, який містить властивості з іменами типу string та значеннями типу number. Ключ [key: string] вказує, що хочемо задати властивості з будь-якими іменами типу string.
Також можна використовувати ключі інших типів, наприклад, числові:
#tsquestions
Об'єкти TypeScript можуть мати лише певні властивості, які були оголошені заздалегідь. Однак, при роботі з деякими API або даними, може виникнути необхідність динамічно створюваних властивостей, які не відомі заздалегідь. У цьому випадку можуть допомогти Index Properties.
Для створення Index Properties використовується наступний синтаксис:
interface MyObject {
[key: string]: number;
}У цьому прикладі ми оголошуємо інтерфейс MyObject, який містить властивості з іменами типу string та значеннями типу number. Ключ [key: string] вказує, що хочемо задати властивості з будь-якими іменами типу string.
Також можна використовувати ключі інших типів, наприклад, числові:
interface MyObject {
[key: number]: string;
}#tsquestions
Optional Chaining
Це спрощення для перевірок, а чи є поле в об'єкті. Можна для цього використовувати Lodash, а можна механізмом у TS.
#tsquestions
Це спрощення для перевірок, а чи є поле в об'єкті. Можна для цього використовувати Lodash, а можна механізмом у TS.
interface Person {
name: string;
additionInfo?: {
someInfo: string;
}
}
const user: Person = {
name: 'Alex'
}
console.log(user?.additionInfo?.someInfo);
Ми поставили? перед викликом властивості у якому ми впевнені цим уникли помилки.#tsquestions
Nullish Coalescing це оператор TypeScript і JavaScript, який дозволяє вибрати значення з двох варіантів, залежно від того, чи є значення "null" або "undefined".
Оператор використовується в наступному синтаксисі:
Тут змінної "result" надається значення "value1", якщо воно не дорівнює "null" або "undefined". Якщо ж "value1" дорівнює "null" або "undefined", то змінній "result" надається значення "value2".
Оператор "??", також відомий як "nullish coalescing operator", відрізняється від оператора "||", який виконує перевірку на хибне значення (falsey), а не лише на "null" або "undefined".
#tsquestions
Оператор використовується в наступному синтаксисі:
result = value1 ?? value2;
Тут змінної "result" надається значення "value1", якщо воно не дорівнює "null" або "undefined". Якщо ж "value1" дорівнює "null" або "undefined", то змінній "result" надається значення "value2".
Оператор "??", також відомий як "nullish coalescing operator", відрізняється від оператора "||", який виконує перевірку на хибне значення (falsey), а не лише на "null" або "undefined".
#tsquestions
Перевантаження операторів (function overloads) - це механізм у TypeScript та інших мовах програмування, який дозволяє визначати кілька версій функції або методу з тим самим ім'ям, але різними параметрами і значеннями, що повертаються.
При використанні навантаження операторів компілятор TypeScript вибирає версію функції або методу, яка відповідає типу та кількості переданих параметрів.
Наприклад, припустимо, у нас є функція "sum", яка повинна складати два числа та повертати їхню суму:
Ми можемо додати перевантажену версію цієї функції, яка прийматиме рядки замість чисел:
У даному випадку ми визначили дві версії функції "sum", які приймають або два числа, або два рядки, і повертають або число, або рядок. Остання версія функції (без параметрів типу) є спільним тілом функції, яке буде виконано, якщо передані параметри не відповідають жодній з перевантажених версій.
При виклику функції "sum" з двома числами буде вибрано відповідну версію функції, яка повертає число. А якщо ми викличемо функцію "sum" з двома рядками, буде вибрано іншу версію функції, яка повертає рядок.
Перевантаження операторів може бути корисним у випадках, коли необхідно обробляти різні типи даних в одній функції або методі. Вона також може покращити читабельність та підтримуваність коду.
#tsquestions
При використанні навантаження операторів компілятор TypeScript вибирає версію функції або методу, яка відповідає типу та кількості переданих параметрів.
Наприклад, припустимо, у нас є функція "sum", яка повинна складати два числа та повертати їхню суму:
function sum(a: number, b: number): number {
return a + b;
}Ми можемо додати перевантажену версію цієї функції, яка прийматиме рядки замість чисел:
function sum(a: string, b: string): string;
function sum(a: number, b: number): number;
function sum(a: any, b: any): any {
return a + b;
}
У даному випадку ми визначили дві версії функції "sum", які приймають або два числа, або два рядки, і повертають або число, або рядок. Остання версія функції (без параметрів типу) є спільним тілом функції, яке буде виконано, якщо передані параметри не відповідають жодній з перевантажених версій.
При виклику функції "sum" з двома числами буде вибрано відповідну версію функції, яка повертає число. А якщо ми викличемо функцію "sum" з двома рядками, буде вибрано іншу версію функції, яка повертає рядок.
Перевантаження операторів може бути корисним у випадках, коли необхідно обробляти різні типи даних в одній функції або методі. Вона також може покращити читабельність та підтримуваність коду.
#tsquestions
Generic function/method
#tsquestions
function merge<T, U>(objA: T, objB: U) {
return Object.assign(objA, objB);
}
const merged = merge({name: 'Alisa'}, {age: 28});
merged.name;
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("hello"); // output1 типу string
let output2 = identity<number>(123); // output2 типу number
У цьому прикладі метод identity є generic-методом, оскільки він може приймати будь-який тип T як вхідний параметр і повертати його як вихідний параметр. Під час виклику методу identity тип параметра T буде вирішуватися автоматично на основі переданого значення. Наприклад:#tsquestions
Ключове слово extends використовується в узагальненому типі (generic type) для визначення обмеження на тип даних, який може бути переданий як параметр типу.
Розглянемо наступний приклад:
Тут extends використовується обмеження типу параметра K лише тими властивостями T, які є ключами (keyof) об'єкта T. Таким чином, при спробі передати некоректний ключ, TypeScript видасть помилку компіляції.
Також extends можна використовувати для обмеження узагальненого типу будь-яким іншим типом, наприклад:
Таким чином, extends використовується в узагальнених типах для визначення обмежень на типи даних, які можуть бути передані як параметри типів.
Розглянемо наступний приклад:
function getObjectProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
У цьому прикладі T і K - це параметри типу. Параметр T може бути будь-яким типом даних, а параметр K це узагальнений тип, який обмежений типом властивості об'єкта T.Тут extends використовується обмеження типу параметра K лише тими властивостями T, які є ключами (keyof) об'єкта T. Таким чином, при спробі передати некоректний ключ, TypeScript видасть помилку компіляції.
Також extends можна використовувати для обмеження узагальненого типу будь-яким іншим типом, наприклад:
interface Fruit {
name: string;
color: string;
}
function getFruit<T extends Fruit>(fruit: T) {
return `${fruit.name} (${fruit.color})`;
}
У цьому прикладі T обмежений інтерфейсом Fruit. Це означає, що параметр fruit має бути об'єктом, що має властивості name та color типу string.Таким чином, extends використовується в узагальнених типах для визначення обмежень на типи даних, які можуть бути передані як параметри типів.
interface Animal {
name: string;
}
function printName<T extends Animal>(animal: T) {
console.log(animal.name);
}
const cat: Animal = { name: 'Fluffy' };
printName(cat); // Виведе 'Fluffy'
const dog = { name: 'Buddy', breed: 'Golden Retriever' };
printName(dog); // Помилка компіляції, оскільки об'єкт dog відповідає інтерфейсу Animal
Ще приклад, що показає, що є така властивість:function printLength<T extends { length: number }>(obj: T) {
console.log(obj.length);
}
const array = [1, 2, 3];
printLength(array); // Виводить 3, оскільки масив має властивість length
const string = 'Hello';
printLength(string); // Виводить 5, тому що рядок має властивість length
const number = 42;
printLength(number); // Помилка компіляції, тому що число не має властивості length
#tsquestionskeyof — дозволяє зробити уточнення, що якийсь тип є ключем в об'єкті.
За допомогою U extends keyof T ми зробили уточнення, що тип U є як ключ у типі T і тепер усе працює.
#tsquestions
function extractValue<T extends object, U extends keyof T> (obj:T, key:U) {
return obj[key];
}
extractValue({name: 'Sergei'}, 'name');За допомогою U extends keyof T ми зробили уточнення, що тип U є як ключ у типі T і тепер усе працює.
#tsquestions
Ми можемо призначити дженерики на клас, це буває зручно, якщо ми хочемо позначити тип, який пронизуватиме весь клас.
class StoreClass<T> {
private data: T[] = [];
addItem (item:T):void {
this.data.push(item);
}
getItems (): T[] {
return this.data;
}
}
І тепер ми можемо контролювати які типи можуть зберігатися як data;const store = new StoreClass<string>();#tsquestions
store.addItem('test');
Utility Types - це вбудовані в TypeScript типи, які надають корисні функції для маніпулювання із типами даних. Давайте розглянемо три з них - Partial, Readonly і Pick:
1. Partial - цей тип дозволяє зробити всі властивості об'єкта необов'язковими, зробивши їх опціональними. Ось приклад використання:
2. Readonly - цей тип дозволяє зробити всі властивості об'єкта не змінюваними, тобто вони стають тільки для читання. Ось приклад використання:
3. Pick - це один з utility типів в TypeScript, який дозволяє створити новий тип, який містить тільки вибрані властивості з існуючого типу.
Наприклад, ми маємо інтерфейс User з властивостями name і age:
Ми можемо створити новий тип, що містить лише властивість name з інтерфейсу User, використовуючи тип Pick:
Тепер тип UserNameOnly буде мати лише одну властивість name, яка є рядком:
Отже, тип Pick дозволяє зробити новий тип з вибраних властивостей іншого типу, що може бути корисним у багатьох випадках в програмуванні.
#tsquestions
1. Partial - цей тип дозволяє зробити всі властивості об'єкта необов'язковими, зробивши їх опціональними. Ось приклад використання:
interface User {
name: string;
age: number;
email: string;
}
function updateUser(user: User, dataToUpdate: Partial<User>): User {
return { ...user, ...dataToUpdate };
}
const user: User = { name: 'John', age: 25, email: 'john@example.com' };
const updatedUser = updateUser(user, { age: 26, email: 'new-email@example.com' });
console.log(updatedUser);
// Output: { name: 'John', age: 26, email: 'new-email@example.com' }
У цьому прикладі функція updateUser приймає об'єкт користувача та об'єкт, що містить дані для оновлення, за допомогою Partial<User>. Це дозволяє передавати тільки певні властивості для оновлення, а решта залишаються незмінними.2. Readonly - цей тип дозволяє зробити всі властивості об'єкта не змінюваними, тобто вони стають тільки для читання. Ось приклад використання:
interface User {
readonly name: string;
readonly age: number;
}
const user: Readonly<User> = { name: 'John', age: 25 };
// Помилка компіляції, не можна змінювати значення поля name
user.name = 'Jane';
// Помилка компіляції, не можна додавати нові поля
user.email = 'john@example.com';
У цьому прикладі ми визначаємо об'єкт користувача з допомогою Readonly<User>. Це дозволяє зробити всі властивості об'єкта тільки для читання, тобто не можна змінювати їх значення після того, як об'єкт був створений.3. Pick - це один з utility типів в TypeScript, який дозволяє створити новий тип, який містить тільки вибрані властивості з існуючого типу.
Наприклад, ми маємо інтерфейс User з властивостями name і age:
interface User {
name: string;
age: number;
}Ми можемо створити новий тип, що містить лише властивість name з інтерфейсу User, використовуючи тип Pick:
type UserNameOnly = Pick<User, 'name'>;
Тепер тип UserNameOnly буде мати лише одну властивість name, яка є рядком:
const user: UserNameOnly = { name: 'John' };Отже, тип Pick дозволяє зробити новий тип з вибраних властивостей іншого типу, що може бути корисним у багатьох випадках в програмуванні.
#tsquestions
Декоратори - це механізм у мовах програмування, таких як TypeScript, JavaScript, Java та інших, що дозволяє обернути функцію, клас або інший об'єкт в іншу функцію, яка змінює його поведінку або додає додаткову функціональність. Декоратори надають гнучкість у додаванні та зміні поведінки коду без необхідності модифікувати його безпосередньо.
Ідея декораторів полягає в тому, що ви можете взяти існуючу функцію або клас і обернути її в іншу функцію, яка виконує певні дії перед або після виклику вихідної функції, або в процесі виконання. При цьому код, що викликає, і сама обернута функція не помічають різниці.
Переваги використання декораторів включають:
1. Модульність та повторне використання коду: Ви можете створювати невеликі декоратори, які вирішують конкретні завдання, а потім комбінувати їх для створення складної поведінки. Це дозволяє легко повторно використовувати код і робить його більш модульним.
2. Розширюваність та гнучкість: Декоратори дозволяють додавати функціональність до існуючого коду без необхідності зміни. Ви можете легко додавати нові декоратори або змінювати порядок застосування існуючих, щоб отримати потрібну поведінку.
3. Поділ відповідальності: Декоратори дозволяють розділяти логіку та відповідальність між різними компонентами коду. Ви можете створювати декоратори, що відповідають за логування, автентифікацію, кешування та інші аспекти функціональності, а потім застосовувати їх до відповідних об'єктів чи функцій.
Приклади використання декораторів можна знайти у різних галузях розробки програмного забезпечення. У React, наприклад, декоратори (звані High Order Components) використовуються додавання додаткової логіки до компонентів. У Node.js, middleware (які також є декораторами) використовуються для обробки проміжних етапів запитів. У TypeScript декоратори можуть застосовуватися до класів, методів, властивостей та параметрів для додавання аспектів, таких як логування, валідація та серіалізація.
Важливо, що декоратори TypeScript зазвичай використовуються за допомогою синтаксису @ім'яДекоратора, який дозволяє застосовувати декоратори до певних елементів коду, таким як класи, методи і властивості, за допомогою явного вказівки декоратора перед визначенням елемента. Це спрощує використання та розуміння декораторів у коді.
Коли компілятор зустрічає @ то він шукає функцію з ім'ям, вказаним після @, обертає в неї те, що наступним рядком: передає в неї відповідні аргументи і забезпечує виклик обгорнутої функції з усіма аргументами виклику після відпрацювання обгортки, за умови, що з неї повернувся undefined.
#tsquestions
Ідея декораторів полягає в тому, що ви можете взяти існуючу функцію або клас і обернути її в іншу функцію, яка виконує певні дії перед або після виклику вихідної функції, або в процесі виконання. При цьому код, що викликає, і сама обернута функція не помічають різниці.
Переваги використання декораторів включають:
1. Модульність та повторне використання коду: Ви можете створювати невеликі декоратори, які вирішують конкретні завдання, а потім комбінувати їх для створення складної поведінки. Це дозволяє легко повторно використовувати код і робить його більш модульним.
2. Розширюваність та гнучкість: Декоратори дозволяють додавати функціональність до існуючого коду без необхідності зміни. Ви можете легко додавати нові декоратори або змінювати порядок застосування існуючих, щоб отримати потрібну поведінку.
3. Поділ відповідальності: Декоратори дозволяють розділяти логіку та відповідальність між різними компонентами коду. Ви можете створювати декоратори, що відповідають за логування, автентифікацію, кешування та інші аспекти функціональності, а потім застосовувати їх до відповідних об'єктів чи функцій.
Приклади використання декораторів можна знайти у різних галузях розробки програмного забезпечення. У React, наприклад, декоратори (звані High Order Components) використовуються додавання додаткової логіки до компонентів. У Node.js, middleware (які також є декораторами) використовуються для обробки проміжних етапів запитів. У TypeScript декоратори можуть застосовуватися до класів, методів, властивостей та параметрів для додавання аспектів, таких як логування, валідація та серіалізація.
Важливо, що декоратори TypeScript зазвичай використовуються за допомогою синтаксису @ім'яДекоратора, який дозволяє застосовувати декоратори до певних елементів коду, таким як класи, методи і властивості, за допомогою явного вказівки декоратора перед визначенням елемента. Це спрощує використання та розуміння декораторів у коді.
Коли компілятор зустрічає @ то він шукає функцію з ім'ям, вказаним після @, обертає в неї те, що наступним рядком: передає в неї відповідні аргументи і забезпечує виклик обгорнутої функції з усіма аргументами виклику після відпрацювання обгортки, за умови, що з неї повернувся undefined.
#tsquestions
https://www.w3schools.com/typescript/exercise.php
Хороший сайт по тренуванню навичкам по TypeScript. Швидко можна освіжити знання чи вивчити нове щось.
Хороший сайт по тренуванню навичкам по TypeScript. Швидко можна освіжити знання чи вивчити нове щось.
Просто про React з фреймворком Redux. Елементарний приклад.
Краще створити окремий файл зі Store, де буде глобальний Store та Reducer’и. В залежності від складності програми - можна збільшувати кількість файлів.
В цьому файлі ми можемо створити для кожного Reducer свій State (стан чи можна назвати об’єкт початкових значень), наприклад,
Потім можна створити Reducer. У Redux Reducer — це функція, яка приймає поточний стан (state) і дію (action), а потім повертає новий стан відповідно до цієї дії.
Щоб отримати повністю актуальний стан сховища, ви можете використовувати метод store.getState()
Стор за допомогою провайдера передається обгорткою вже в react компоненти
<Provider store={store}>
<App />
</Provider>
Переходимо на сторінку будь якого компонету.
Коли ви викликаєте useSelector(state => state.cash), функція useSelector приймає як аргумент функцію-селектор. Ця функція визначає, яке значення стану потрібно отримати.
React Redux самостійно підписується на зміни стану, і коли стан змінюється (наприклад, після диспетчеризації дії), React Redux оновлює компонент, що використовує useSelector, щоб відобразити нове значення cash.
Таким чином, при використанні useSelector(state => state.cash) ви отримуєте поточне актуальне та оновлюване значення cash зі стану Redux.
Коли ви використовуєте хук useDispatch() з бібліотеки React Redux, функція dispatch автоматично надсилає дані (дії) у відповідний редьюсер.
У Redux кожна дія (action) повинна мати поле type, яке вказує на тип дії. Це дозволяє редьюсеру визначити, які зміни потрібно внести до стану на основі цієї дії.
При викликі dispatch({ type: "ADD_CASH", payload: cash }) ви відправляєте дію з типом "ADD_CASH" та полем payload, яке містить дані (в даному випадку значення cash).
Redux використовує цей тип дії для визначення, який редьюсер повинен обробити цю дію. Коли ви створюєте сховище та комбінуєте ваші редьюсери за допомогою функції combineReducers, кожен редьюсер прослуховуватиме відповідний тип дії.
У прикладі редьюсер, який оброблятиме дію з типом "ADD_CASH", вже доданий у функцію combineReducers. Це означає, що ред'юсер, який відповідає за зміну стану типу дії "ADD_CASH", буде викликаний автоматично при виклику dispatch({ type: "ADD_CASH", payload: cash }).
Таким чином, функція dispatch розуміє, в який редьюсер потрібно відправити дані, виходячи з зазначеного типу дії. Це дозволяє Redux обробляти дії та вносити відповідні зміни до стану вашої програми.
Краще створити окремий файл зі Store, де буде глобальний Store та Reducer’и. В залежності від складності програми - можна збільшувати кількість файлів.
В цьому файлі ми можемо створити для кожного Reducer свій State (стан чи можна назвати об’єкт початкових значень), наприклад,
const defaultState = {
cash: 5,
}
Зазвичай стан (state) в Redux може бути представлено різними типами даних залежно від ваших потреб. Але найбільш поширеним та рекомендованим підходом є використання об'єкта для представлення стану.Потім можна створити Reducer. У Redux Reducer — це функція, яка приймає поточний стан (state) і дію (action), а потім повертає новий стан відповідно до цієї дії.
const countReduser = (state = defaultState, action) => {
switch(action.type) {
case “ADD_CASH”:
return {
…state,
cash: state.cash + action.payload
}
..
default:
return state;
}
}
Далі створити сам Storeconst store = Redux.createStore(rootReducer);Або якщо reducer’ів більше одного, можна використати combineReducers. Redux.createStore створює сховище (store), яке зберігатиме об'єднаний стан, керований усіма редьюсерами, переданими у функцію Redux.combineReducers.
const rootReducer = Redux.combineReducers({
auth:authReducer,
count:counterReducer,
})
Якщо не писати auth та count то буде під капотом authReducer: authReducerStore об'єднує два редьюсера authReducer і counterReducer в один корневий редьюсер. В результаті створюється хранилище, яке містить стан, кероване кожним із редьюсеров. Коли ви звертаєтеся до
store.getState().auth, ви отримуєте поточний стан, керований редьюсером authReducer.
Щоб отримати повністю актуальний стан сховища, ви можете використовувати метод store.getState()
const state = store.getState(); // Отримання повного життєвого стану сховищаНа цьому все зі Store сторінкою, щодо action.type case “ADD_CASH”: - про це далі.
console.log(state);
Стор за допомогою провайдера передається обгорткою вже в react компоненти
<Provider store={store}>
<App />
</Provider>
Переходимо на сторінку будь якого компонету.
const dispatch = useDispatch()Хук useSelector із бібліотеки React Redux автоматично шукає значення cash у стані (store) Redux.
const cash = useSelector(state => state.cash)
const addCash = (cash) => {
dispatch({type:”ADD_CASH”, payload: cash})
}
<button onClick={()=>addCash(Number(prompt())}Press</button>
Коли ви викликаєте useSelector(state => state.cash), функція useSelector приймає як аргумент функцію-селектор. Ця функція визначає, яке значення стану потрібно отримати.
React Redux самостійно підписується на зміни стану, і коли стан змінюється (наприклад, після диспетчеризації дії), React Redux оновлює компонент, що використовує useSelector, щоб відобразити нове значення cash.
Таким чином, при використанні useSelector(state => state.cash) ви отримуєте поточне актуальне та оновлюване значення cash зі стану Redux.
Коли ви використовуєте хук useDispatch() з бібліотеки React Redux, функція dispatch автоматично надсилає дані (дії) у відповідний редьюсер.
У Redux кожна дія (action) повинна мати поле type, яке вказує на тип дії. Це дозволяє редьюсеру визначити, які зміни потрібно внести до стану на основі цієї дії.
При викликі dispatch({ type: "ADD_CASH", payload: cash }) ви відправляєте дію з типом "ADD_CASH" та полем payload, яке містить дані (в даному випадку значення cash).
Redux використовує цей тип дії для визначення, який редьюсер повинен обробити цю дію. Коли ви створюєте сховище та комбінуєте ваші редьюсери за допомогою функції combineReducers, кожен редьюсер прослуховуватиме відповідний тип дії.
У прикладі редьюсер, який оброблятиме дію з типом "ADD_CASH", вже доданий у функцію combineReducers. Це означає, що ред'юсер, який відповідає за зміну стану типу дії "ADD_CASH", буде викликаний автоматично при виклику dispatch({ type: "ADD_CASH", payload: cash }).
Таким чином, функція dispatch розуміє, в який редьюсер потрібно відправити дані, виходячи з зазначеного типу дії. Це дозволяє Redux обробляти дії та вносити відповідні зміни до стану вашої програми.
Простий JavaScript — все про js, ts, node.js, react
Просто про React з фреймворком Redux. Елементарний приклад. Краще створити окремий файл зі Store, де буде глобальний Store та Reducer’и. В залежності від складності програми - можна збільшувати кількість файлів. В цьому файлі ми можемо створити для кожного…
Простий JavaScript — все про js, ts, node.js, react
Просто про React з фреймворком Redux. Елементарний приклад. Краще створити окремий файл зі Store, де буде глобальний Store та Reducer’и. В залежності від складності програми - можна збільшувати кількість файлів. В цьому файлі ми можемо створити для кожного…
Щоб створити окремий файл Store з глобальним станом і редюсерами, ви можете використовувати функцію createSlice з бібліотеки Redux Toolkit. Ось приклад, як це можна зробити:
1) Створіть новий файл, наприклад store.js, і підключіть необхідні залежності:
4)Експортуйте дії та редюсер з вашого файлу store.js:
Тепер ви можете використовувати YourComponent з вашим глобальним станом та діями, які змінюють цей стан.
можна створити два редюсера
1) Створіть новий файл, наприклад store.js, і підключіть необхідні залежності:
import { configureStore, createSlice } from '@reduxjs/toolkit';
2)Визначте початковий стан для вашого редюсера:const initialState = {
cash: 5,
};
3)Створіть редюсер за допомогою функції createSlice:const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
addCash: (state, action) => {
state.cash += action.payload;
},
},
});
У цьому прикладі ми створили редюсер з ім'ям "counter" та однією дією "addCash". Дія "addCash" змінює значення cash у стані, додаючи значення payload з дії.4)Експортуйте дії та редюсер з вашого файлу store.js:
export const { addCash } = counterSlice.actions;
export default configureStore({
reducer: counterSlice.reducer,
});
5)Використовуйте ваш стор у вашому головному компоненті, обернувши його <Provider>:import React from 'react';6)В вашому компоненті YourComponent використовуйте хуки useSelector та useDispatch для отримання стану та диспетчеризації дій:
import { Provider } from 'react-redux';
import store from './store';
import YourComponent from './YourComponent';
const App = () => {
return (
<Provider store={store}>
<YourComponent />
</Provider>
);
};
export default App;
import React from 'react';В цьому прикладі ми використовуємо хук useSelector для отримання значення cash зі стану, а також хук useDispatch для диспетчеризації дії addCash з вказаною сумою.
import { useSelector, useDispatch } from 'react-redux';
import { addCash } from './store';
const YourComponent = () => {
const cash = useSelector((state) => state.cash);
const dispatch = useDispatch();
const handleAddCash = (amount) => {
dispatch(addCash(amount));
};
return (
<div>
<p>Cash: {cash}</p>
<button onClick={() => handleAddCash(10)}>Add Cash</button>
</div>
);
};
export default YourComponent;
Тепер ви можете використовувати YourComponent з вашим глобальним станом та діями, які змінюють цей стан.
можна створити два редюсера
const rootReducer = combineReducers({
counter: counterReducer,
auth: authReducer,
});export default configureStore({
reducer: rootReducer,
});Хук useEffect
1)запускається при кожному рендері чи зміні якогось стану в цьому компоненті, де він використовується
1)запускається при кожному рендері чи зміні якогось стану в цьому компоненті, де він використовується
useEffect(() => {
console.log('hello');
} )
2) запускається Тільки при рендері, залежність вказана нульоваuseEffect(() => {
console.log('hello');
}, [])
3) запускається при рендері першому та з залежністю від зміни пропа countuseEffect(() => {
console.log('hello');
}, [count])
4) всередині можна написати return і тоді це виконається коли компонент розрендериться useEffect(() => {
// Оновлення кожну секунду
const interval = setInterval(() => {
setCurrentTime(new Date());
}, 1000);
// Очистка інтервалу при видаленні компонента
return () => clearInterval(interval);
}, []);Хук useState
Є "Лінива ініціалізація", коли можна передати функцію саме як анонімку
Є "Лінива ініціалізація", коли можна передати функцію саме як анонімку
const [time, setTime] = useState (()=>new Date())Тоді вона викликається тільки один раз