React Junior
207 subscribers
37 photos
462 links
Изучение React с нуля
加入频道
atomFamily и selectorFamily

Это две полезные утилиты, которые позволяют создавать коллекции атомов или селекторов. Утилите нужно передать параметр, который по сути станет идентификатором значения.

При передаче разных параметров вернутся разные (разные экземпляры) атомы/селекторы, при передаче одного - один (причем даже в разных частях приложения).

Параметр при этом можно использовать.

Например, для определения дефолтного значения атома при создании:

const myAtomFamily = atomFamily({
key: 'MyAtom',
default: function(param) {
return `atom-${param}`;
}
})

Или (как мы уже делали) как параметр запроса внутри селектора:

const mySelectorFamily = selectorFamily({
key: 'MySelector',
get: function(param) {
return async function() {
const response = await fetch(`/get-data?id=${param}`);
return response;
}
}
})

Пример: https://codesandbox.io/s/recoil-atomfamily-react-junior-bj84yl

Создаем с помощью myAtomFamily два атома с разными параметрами (1 и 2). Их можно использовать и изменять отдельно. По этому параметру их можно получить в другом компоненте, при этом значение будет синхронизировано.

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

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

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

const myAtomFamily = atomFamily({
key: 'MyAtom',
default: selectorFamily({
key: 'MyAtom/Default',
get: function(param) {
// param - это параметр атома, atomFamily(param)

return function({ get }) {
// Это обычный селектор, он может быть асинхронным
}
}
})
})


#recoil #управлениесостоянием #документация #примерыкода
👍1
14 лучших каруселей для React-проектов

Статья (англ.): https://medium.com/@vdas53073/14-top-react-carousel-components-2022-%EF%B8%8F-d89b4a84f249

14 готовых компонентов для реализации карусели на React. Кроме старых добрых Swiper, Slick, Owl Carousel есть еще много хороших решений на любой вкус.

#tools #library #react #interface
👍1
Recoil. Сброс кеша. 1 вариант

Мы уже увидели, что селекторы в Recoil кешируют полученные данные (с привязкой к своим зависимостям). Но иногда кеш нужно сбросить. Для этого есть несколько способов:

useRecoilRefresher()

Хук useRecoilRefresher_UNSTABLE получает селектор и возвращает функцию для сброса его кеша.

Работает и с обычным селектором, созданным с помощью selector, и с параметризованным селектором, созданным/полученным с помощью selectorFamily (в этом случае кеш сбрасывается только для одного параметра)ж

Пример 1: сброс обычного селектора (https://codesandbox.io/s/recoil-refresh-cache-1-react-junior-m9i09t?file=/src/components/UserInfo.js)
Пример 2: сброс селектора с параметром (https://codesandbox.io/s/recoil-refresh-cache-2-react-junior-secreg?file=/src/components/UserInfo.js)

#recoil #управлениесостоянием #документация #примерыкода
👍1
Recoil. Сброс кеша. 2 вариант

Другой вариант сбросить кеш селектора - использовать id запроса. Простыми словами, мы добавляем в селектор дополнительную зависимость. Если нужно обновить данные, просто изменяем значение этой зависимости и селектор перезагружается.

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

const userDataQueryRequestIdState = atomFamily({
key: "UserDataQueryRequestId",
default: 0
});


Добавляем в селектор новую зависимость:

const userDataQuery = selectorFamily({
key: "UserDataQuery",
get: (userId) => async ({ get }) => {
get(userDataQueryRequestIdState(userId));

const response = await getUserInfo(userId);

if (response.error) {
throw response.error;
}
return response;
}
});


И пишем кастомный хук для обновления id запроса для конкретного параметра:

function useRefreshUserData(userId) {
const setUserInfoQueryRequestId = useSetRecoilState(
userDataQueryRequestIdState(userId)
);
return () => {
setUserInfoQueryRequestId((requestId) => requestId + 1);
};
}


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

Пример: https://codesandbox.io/s/recoil-refresh-cache-3-react-junior-rm4tll?file=/src/components/Refresh.js

#recoil #управлениесостоянием #документация #примерыкода
👍2
Recoil. Сброс кеша. 3 вариант

Самый простой вариант избежать кеширования данных - хранить состояние в атоме и обновлять его вручную (делать запрос в компоненте и устанавливать новое значение). В этом случае придется отдельно хранить также состояние запроса, так как React Suspense не узнает об этих изменениях.

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

В Recoil есть возможность устанавливать "эффекты" для атомов. Это похоже на хук useEffect - эффекты срабатывают при инициализации атома (при первом использовании внутри RecoilRoot).

Указывать эффекты нужно в массиве effects в определении атома:


const counterState = atom({
key: 'Counter',
default: 0,
effects: [
function() {
console.log('Init atom effect');
}
]
})


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


effects: [
function() {
const interval = setInterval(...);

return function() {
clearInterval(interval);
}
}
]


Каждый эффект в качестве аргумента принимает объект с кучей полезных методов. Среди них, например, onSet, который позволяет подписаться на изменение значения атома.


effects: [
function({ onSet }) {
onSet(function(newValue) {
console.log('Atom value updated:', newValue);
})
}
]


Использовать эффекты атомов можно, например, для логирования или сохранения истории действий и функционала "Шаг назад".

Пример с логированием значений счетчика: https://codesandbox.io/s/recoil-atom-effects-react-junior-ukjg6f?file=/src/state.js

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

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


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