React Junior
207 subscribers
37 photos
462 links
Изучение React с нуля
加入频道
Эффекты атомов

Пример использования эффектов атомов из документации (сихронизация значения атома с каким-то удаленным хранилищем):


const syncStorageEffect = function(userID) {
return function({setSelf, trigger}) {
// Установка значения при инициализации атома
if (trigger === 'get') {
setSelf(myRemoteStorage.get(userID)); // Выполнятся синхронно при инициализации
}

// Подписка на удаленное хранилище и синхронизация значений
myRemoteStorage.onChange(userID, function(userInfo) {
setSelf(userInfo); // Выполняется асинхронно при изменении значения
});

// Сброс подписки на хранилище
return function() {
myRemoteStorage.onChange(userID, null);
};
}
};

const userInfoState = atomFamily({
key: 'UserInfo',
default: null,
effects: userID => [
syncStorageEffect(userID),
],
})


1) Эффекты можно использовать и с семьей атомов, просто вместо массива функций-эффектов должна быть функция, которая возвращает массив функций-эффектов.

2) Параметр trigger обозначает действие, которое вызвало инициализацию атома.

3) Метод setSelf позволяет переписать значение атома изнутри эффекта.

#recoil #управлениесостоянием #документация #примерыкода
🔥1
Эффекты атомов

Итак, метод onSet внутри эффекта позволяет подписаться на изменения значения атома, а метод setSelf позволяет изменить это значение.
Чтобы не возникало зацикливание, подписка onSet не срабатывает при изменениях через setSelf.

#recoil #управлениесостоянием #документация
👍1
Эффекты атомов

В метод setSelf можно передать промис - для асинхронного обновления значения.

#recoil #управлениесостоянием #документация
👍1
Recoil. Резюме

Думаю, общее представление о Recoil составлено. Выглядит интересно, максимально близок к самому React, но как будто сыроват: unstable-методы, мало руководств, хотя в продакшене он уже используется.

Может быть, вернусь к нему позднее.

Материалы по Recoil:

- документация
- репозиторий
- видео-курс (англ.) - около 20 уроков

#recoil #управлениесостоянием #ссылки #отложено
👍1
TypeScript

По плану сейчас идет должно быть знакомство с MobX, но очень хочется заняться TypeScript`ом уже. Все-таки это очень нужная штука сейчас.

#typescript #отложено
👍6
TypeScript. Начало работы, компиляция

1. Создаем новый npm-проект


npm init -y


2. Устанавливаем пакет typescript


npm install typescript


3. Теперь в нашем проекте появилась утилита tsc - компилятор TypeScript в JavaScript.

4. Нужно создать файл tsconfig.json в директории проекта. Можно сделать это вручную, а можно с помощью команды


npx tsc --init


Эта команда сгенерирует базовую конфигурацию.

5. Теперь создадим первый TypeScript-файл - index.ts. Напишем в нем что-нибудь вот такое:


function sum(item1: number, item2: number):number {
return item1 + item2;
}

const res1 = sum(3, 4);


6. Нужно скомпилировать ts-код в обычный JavaScript, для этого выполняем команду:


npx tsc index.ts


В проекте появится новый скомпилированный файл index.js:


function sum(item1, item2) {
return item1 + item2;
}
var res1 = sum(3, 4);


В этом коде уже нет типов - это обычный JS, даже с var вместо const.

Вот, теперь мы умеем компилировать TypeScript.

Что примечательно, проверка типов идет уже во время создания кода в самом редакторе (VS Code). Если дописать еще одну строчку с ошибкой типов


const res2 = sum('hello', 'world');


появится предупреждение.

Если влом устанавливать, можно поиграть в официальной песочнице: https://www.typescriptlang.org/play

#typescript
👍1
TypeScript. Начало работы

Основная идея TypeScript как будто понятна: мы указываем типы переменных и параметров, а инструмент следит, чтобы эти типы соблюдались. Если попробовать скомпилировать код с ошибками, в консоли будут подробные сообщений - где и что не так.

Тип указывается через двоеточие:


Для переменной:


const numberVariable: number = 42;
const stringVariable: string = 'Hello';


Для входных параметров функции:


function sum(a:number, b:number) {

}


Для выходного значения функции:


function sum(a,b): number {

}


#typescript
👍3
Forwarded from Cat in Web
JavaScript vs TypeScript. Почему Вы должны изучить TypeScript?

Статья (рус.): https://habr.com/ru/post/660791/

TypeScript контролирует типы данных в вашем коде (переменных, параметров функции) и предотвращает множество ошибок, связанных с несовместимостью типов. Он предлагает статическую типизацию вместо динамической (JavaScript).

В статье описаны основы TypeScript, так что ее можно использовать для создания первого впечатления об инструменте.

🔹 Примитивные типы данных: string, number, boolean, null, undefined
🔹 Магический тип данных any и нужен ли он
🔹 Автоматическое определение типа данных при создании переменных
🔹 Интерфейсы для определения объектов
🔹 Типы данных для массивов (два способа указания)
🔹 Представление о дженериках (понятно, как работают, не понятно, в каких ситуациях использовать)
🔹 Объединение (union) - возможность указать несколько типов на выбор
🔹 Кортеж (tuple) - набор элементов с разными типами

#typescript #junior
👍4
TypeScript: Раскладываем tsconfig по полочкам

Разберемся в основных настройках TypeScript.

Статьи (рус.):
Часть 1
Часть 2

Исходные и конечные файлы

files, include, exclude - принимают массивы с именам файлов (или шаблонами имен).

compilerOptions.allowJs, compilerOptions.checkJS - работа с JS-файлами (например, при миграции проекта с JS на TS).

compilerOptions.outDir, compilerOptions.outFile - директория и имя файла для итоговой сборки.

compilerOptions.resolveJsonModule - можно импортировать JSON-файлы.

jsx - работа с JSX-разметкой (в React).

Работа с модулями

compilerOptions.module - система модулей, которую будет использовать скомпилированное приложение. По умолчанию commonjs (exports, require), можно поставить 'es6' для фронтенд-проектов.

compilerOptions.moduleResolution - стратегия импорта модулей, в подавляющем большинстве случаев значение параметра равно node.

compilerOptions.esModuleInterop - позволяет импортировать CommonJs-пакеты в стиле ES6.

compilerOptions.forceConsistentCasingInFileNames - режим чувствительности к регистру импортируемых файлов.

Использумая функциональность

compilerOptions.target - версия стандарта JS, в которую компилируется исходный код. По умолчанию (в сгенерированном файле) стоит es2016, который поддерживается большинством браузеров.

compilerOptions.compilerOptions.lib - сторонняя функциональность, которая используется в проекте (полифиллы). По умолчанию для target: es6 подключаются методы стандарта ES6, а также DOM, DOM.Iterable, ScriptHost.

Строгость

compilerOptions.strict - включает строгий режим JS и ряд строгих проверок (на использование типа any, неявного this и т.д.). Можно заменить набором отдельных настроек.

Линтинг

compilerOptions.noImplicitReturns, compilerOptions.noUnusedParameters, compilerOptions.allowUnreachableCode, compilerOptions.removeComments и тому подобное.

Компиляция

compilerOptions.noEmitOnError - не прерывать компиляцию при ошибке.

#typescript #подключение
👍1
TypeScript. Типы данных

Типы, знакомые из JavaScript:

- string
- number
- boolean
- null
- undefined
- object

Особые типы:

- void (для функций, которые ничего не возвращают)
- never (для функций, которые никогда не завершаются)

Еще есть массивы, кортежи, перечисления и функции (о них в следующих постах)

#typescript
👏2👍1
TypeScript. Массивоподобные типы

1. Массив, все элементы которого имеют одинаковый тип данных (массив чисел, массив строк)

Есть два способа определить массив:

- указываем тип данных, а после него квадратные скобки
- указываем конструктор Array, а после него в угловых скобках тип. Такая запись называется дженерик, вернемся к ним позже.

2. Массив с известным числом и порядком элементов разных типов (кортеж)

- в квадратных скобках перечисляются типы всех элементов по порядку

#typescript
👍2🔥2
TypeScript. Перечисления (enums)

Видео (рус.): https://www.youtube.com/watch?v=FltLrtKWMak

Перечисление, или enum, - это способ создать коллекцию ключей, каждому из которых будет сопоставлено уникальное значение.


enum Directions {
Up,
Down,
Left,
Right,
}


Под капотом у нас создается структура (среднее между массивом и объектом), содержащая четыре элемента. Каждому из них выдается порядковый номер.

Up, Down, Left, Right - это как бы названия свойств коллекции.


Directions.Up // 0
Directions.Down // 1


Отличное решение для хранения наборов констант, к которым можно обращаться по имени.

Если дефолтный порядок нумерации не устраивает, можно установить любые кастомные индексы:


enum Directions {
Up = 2,
Down = 4,
Left = 6,
Right = 8,
}


Можно, наоборот, получать элементы по индексу:


Directions[6] // 'Left'


Можно вместо индексов использовать строковые значения:


enum Links {
vk = 'https://vk.com/',
youtube = 'https://youtube.com'/,
facebook = 'https://facebook.com/'
}


В видео чуть поглубже показано подкапотное поведение enum. В частности, про то, что enum компилируется в вызов функции (IIFO), создающий объект с коллекцией. То есть объект создается в любом случае, даже если не используется.

Но если добавить к объявлению перечисления слово const, то объект не будет создан, если к нему нет ни одного обращения в дальнейшем.

#typescript
👍3
TypeScript. Аргументы функций

#typescript
2🔥1
TypeScript. Функция как тип

Как описать переменную, если в ней должна лежать функция? Как ни странно, с помощью стрелочной функции.

#typescript
👍1🔥1
TypeScript. Кастомные типы данных

Можно создавать собственные типы данных с помощью ключевого слова type:


type Name = string;
const userName1: Name = 'John';
const userName2: Name = 'Jane';


Таким же образом можно создавать сложные типы (объекты):


type Person = {
name: string,
age: number,
nickName?: string
}


Свойства со знаками вопроса - необязательные.

Такой тип можно переиспользовать много раз:


const user1: Person = { name: 'John', age: 25, nickName: 'Zorro' };
const user2: Person = { name: 'Jane', age: 23 };


Это намного удобнее, чем указывать тип сразу для переменной:


const user3: { name: string, age: number, nickName?: string } = { name: 'Robert', age: 30 };


Важно: если присвоить в переменную объект, у которого будут "лишние" свойства (не описанные в типе), TypeScript выбросит ошибку.

#typescript
👍1🔥1
TypeScript. Классы, свойства классов

Классы в TS определяются точно так же, как в JS:

class User {

}


В TS мы можем объявить поля класса и указать их типы:

class User {

name: string;
age: number = 20;
nickName: string = 'Superman';
private secret = '12345';

constructor(name: string, age: number, nickName: string) {
this.name = name;
this.age = age;
this.nickName = nickName;
}

}


Есть модификаторы доступа:
- public (по умолчанию все свойства публичные)
- private (доступны только внутри текущего класса)
- protected (доступны внутри текущего класса и его подклассов)
- readonly

Также свойствам можно указывать значения по умолчанию.

Чтобы не дублировать код свойств три раза (определение в классе, параметры конструктора и присвоение в конструкторе), можно определять их сразу в конструкторе:

class User {
constructor(
public name: string,
public age: number,
public nickName: string
) {

}
}


Тут обязательно указывать модификаторы для каждого свойства. Все свойства, указанные таким образом автоматически присвоятся одноименным полям класса.

#typescript
👍1🔥1
TypeScript. Классы, статические свойства

Для объявления статических свойств (принадлежащих классу, а не экземпляру), используется ключевое слово static:

class User {
static secret = 12345;
}


Это то же самое, что и

class User {}
User.secret = 12345;


#typescript
👍1🔥1
TypeScript. Абстрактные классы

В TypeScript есть возможность создавать абстрактные классы - концепция из сферы полиморфизма, обеспечивающая общий интерфейс для обычных классов, наследующих от абстрактного. При этом экземпляры абстрактного класса напрямую создавать нельзя.

abstract class User {
constructor(
public name: string,
public age: number
) {}

greet(): void {
console.log(this.name);
}

abstract getPass(): string;
}


В абстрактном классе могут быть как обычные методы (с реализацией), так и абстрактные (без реализации, только с сигнатурой). При этом подклассы должны реализовать все заявленные абстрактные методы сами.

#typescript
👍1🔥1
TypeScript. Интерфейсы

Интерфейс - надобъектная сущность, которая описывает, как должен выглядеть объект.

interface User {
name: string,
age?: number
}


Это похоже на простое создание кастомного типа:

type User = {
name: string,
age: number
}


И используется интерфейс так же, как обычный тип:

const john: User = {
name: 'John',
age: 30
}


Но интерфейс - более мощная концепция. Если type это просто создает псевдоним для типа, то интерфейс - это именованный тип объекта, который может наследоваться и расширяться другими интерфейсами.

В интерфейсах также доступен модификатор readonly:

interface User {
readonly name: string,
}


Если сразу не известно, сколько свойств должно быть в объекте, или неизвестны их имена, или они не важны для определяемого интерфейса, можно сделать так:

interface User {
name: string,
age: number,
[propName: string]: any
}


Интерфейсы могут описывать даже классы (похоже на абстрактный класс https://yangx.top/react_junior/401):

interface User {
name: string,
age: number,
getPass(): string
}


Чтобы реализовать этот интерфейс, заинтересованный класс использует ключевое слово implements:

class Admin implements User {
name: string,
age: number,

nickName: string,

getPass() {
return `${this.name}${this.age}`;
}
}


В классе при этом могут быть и дополнительные поля и методы, интерфейс лишь определяет минимальный набор полей.

Класс может реализовывать сразу несколько интерфейсов (перечисляются через запятую):

interface User {
name: string,
age: number
}

interface Pass {
getPass(): string,
}

class Admin implements User, Pass {
name: string,
age: number,

getPass() {
return `${this.name}${this.age}`;
}
}


А сами интерфейсы могут наследовать от других интерфейсов:

interface Admin extends User {
getPass(): string,
}


#typescript
👍1🔥1
TypeScript. Дженерики

Предположим, у нас есть функция, которая получает входной параметр и просто возвращает его. Причем параметр может быть любого типа:

const foo = function(data: any): any {
return data;
}

С точки зрения TS функция валидная, однако компилятор не может определить, с каким типом данных он работает, поэтому возможны ошибки, которые он не сможет поймать:

foo(10).length;

Чтобы вернуть контроль, нам нужно точнее указать тип. Как минимум, показать, что на выходе будет то же самое, что и на входе - один и тот же тип. Для этого в TS есть дженерики (обобщения).

Дженерик - это способ обозначить тип, не называя его напрямую. Обычно для обозначения типа используют букву T (type), но можно взять и другие буквы.

#typescript #дженерики
👍1🔥1