Анонс TypeScript Native
Вышла превью версия TypeScript написанная на Go. Ее можно установить через npm:
Этот пакет предоставляет команду tsgo – он работает аналогично команде tsc. Со временем команда tsgo переименуется в tsc и переедет в пакет typescript. Сейчас команды разделены для удобства тестирования.
Помимо команды tsgo появилось расширение в VS Code для использования TypeScript Language Service на Go в редакторе – “TypeScript (Native Preview)”. С этим расширением должны ускориться такие функции, как go-to-definition, автокомоплит подсказок, вывод ошибок, показ всплывающих подсказок и другое.
https://devblogs.microsoft.com/typescript/announcing-typescript-native-previews/
Вышла превью версия TypeScript написанная на Go. Ее можно установить через npm:
npm install -D @typescript/native-previewЭтот пакет предоставляет команду tsgo – он работает аналогично команде tsc. Со временем команда tsgo переименуется в tsc и переедет в пакет typescript. Сейчас команды разделены для удобства тестирования.
Помимо команды tsgo появилось расширение в VS Code для использования TypeScript Language Service на Go в редакторе – “TypeScript (Native Preview)”. С этим расширением должны ускориться такие функции, как go-to-definition, автокомоплит подсказок, вывод ошибок, показ всплывающих подсказок и другое.
https://devblogs.microsoft.com/typescript/announcing-typescript-native-previews/
Microsoft News
Announcing TypeScript Native Previews
Previews of the native TypeScript port are now available on npm and for VS Code through the Visual Studio Marketplace!
👍24🔥4❤2
Почему Error Boundary, а не просто try/catch для компонентов
В React нельзя использовать try/catch чтобы отловить ошибки рендера компонента. Это связано с тем, что React не вызывает функцию Calculator когда он создает элемент, он лишь создает описание того что надо отрендерить.
Поэтому если обернуть объявление выше в try/catch можно получить только ошибки во время создания этих элементов, а не ошибки рендера. Реальные ошибки происходят внутри компонента, во время рендера, эффектов и обработчиков ошибок.
По примеру выше можно обернуть в try/catch тело компонента, но это лишь обработает ошибки на уровне данного компонента.
Для обработки ошибок внутри компонента используют Error Boundary. Рекомендуется использовать библиотеку react-error-boundary, которая предоставляет готовый компонент ErrorBoundary и хук useErrorBoundary для обработки ошибок в асинхронных колбеках, эффектах, обработчиках ошибок. Пример использования хука:
https://www.epicreact.dev/why-react-error-boundaries-arent-just-try-catch-for-components-i6e2l
В React нельзя использовать try/catch чтобы отловить ошибки рендера компонента. Это связано с тем, что React не вызывает функцию Calculator когда он создает элемент, он лишь создает описание того что надо отрендерить.
const element = (
<div>
<h1>Calculator</h1>
<Calculator left={1} operator="+" right={2} />
<Calculator left={1} operator="-" right={2} />
</div>
)
Поэтому если обернуть объявление выше в try/catch можно получить только ошибки во время создания этих элементов, а не ошибки рендера. Реальные ошибки происходят внутри компонента, во время рендера, эффектов и обработчиков ошибок.
function Calculator(props) {
try {
// ...render logic
} catch (error) {
return <div>Ошибка!</div>
}
}
По примеру выше можно обернуть в try/catch тело компонента, но это лишь обработает ошибки на уровне данного компонента.
Для обработки ошибок внутри компонента используют Error Boundary. Рекомендуется использовать библиотеку react-error-boundary, которая предоставляет готовый компонент ErrorBoundary и хук useErrorBoundary для обработки ошибок в асинхронных колбеках, эффектах, обработчиках ошибок. Пример использования хука:
import { useErrorBoundary } from 'react-error-boundary'
function MyComponent() {
const { showBoundary } = useErrorBoundary()
async function handleClick() {
try {
await doSomethingAsync()
} catch (error) {
showBoundary(error)
}
}
return <button onClick={handleClick}>Do something</button>
}
https://www.epicreact.dev/why-react-error-boundaries-arent-just-try-catch-for-components-i6e2l
Epic React
Why React Error Boundaries Aren't Just Try/Catch for Components
A deep dive into how React error boundaries work, why they're different from try/catch, and how to use them effectively in your apps.
🔥13👍8❤6
Остерегайтесь скрытых проблем при работе с search params
Типо-безопасность — это только вершина айсберга, о которой вспоминают разработчики при работе с search params. Автор библиотеки nuqs предупреждает о скрытых проблемах при работе с search params.
Запись и чтение. Для получения типо-безопасного стейта search params необходимо внедрять библиотеки валидации (например Zod). Для записи в search params сложных стейтов, а потом для их чтения обратно, понадобятся функции сериализации и парсинга соответственно. В nuqs из коробки есть встроенные парсеры для основных типов данных.
Помимо типо-безопасности, при чтении search params важно иметь runtime-безопасность. Даже после парсинга в корректный тип данных, это значение может быть невалидным. Например, значение валидно если находится в диапазоне -90/+90 или -180/+180. Или email написан правильно. Поэтому после парсинга должна происходить валидация данных. Аналогично, перед сериализацией должна происходить валидация, чтобы в URL не попали невалидные значения.
Еще одна из скрытых проблем при работе с URL – частота обновления URL. У разных браузеров есть разный лимит на частоту обновлений URL (в Chrome это 50мс). Проблема может возникнуть из-за привязки URL к высокочастотному инпуту, например
Со временем схема стейта в URL может изменяться, т.е. могут переименовываться поля, удаляться или добавляться новые. Нужно поддержать возможность миграции на новую схему.
При изменении URL может происходить замена текущей истории или добавлении в историю нового URL. При добавлении URL в историю появляется возможность управлять историей через браузерные кнопки вперед/назад. Это удобно для пользователя, но добавляет сложность для разработки, т.к. появляется два источника управления историей: через UI и браузерные кнопки вперед/назад. Например, при открытии модального окна добавляется в историю
https://nuqs.47ng.com/blog/beware-the-url-type-safety-iceberg
Типо-безопасность — это только вершина айсберга, о которой вспоминают разработчики при работе с search params. Автор библиотеки nuqs предупреждает о скрытых проблемах при работе с search params.
Запись и чтение. Для получения типо-безопасного стейта search params необходимо внедрять библиотеки валидации (например Zod). Для записи в search params сложных стейтов, а потом для их чтения обратно, понадобятся функции сериализации и парсинга соответственно. В nuqs из коробки есть встроенные парсеры для основных типов данных.
Помимо типо-безопасности, при чтении search params важно иметь runtime-безопасность. Даже после парсинга в корректный тип данных, это значение может быть невалидным. Например, значение валидно если находится в диапазоне -90/+90 или -180/+180. Или email написан правильно. Поэтому после парсинга должна происходить валидация данных. Аналогично, перед сериализацией должна происходить валидация, чтобы в URL не попали невалидные значения.
Еще одна из скрытых проблем при работе с URL – частота обновления URL. У разных браузеров есть разный лимит на частоту обновлений URL (в Chrome это 50мс). Проблема может возникнуть из-за привязки URL к высокочастотному инпуту, например
<input type="text"> или <input type="range">.Со временем схема стейта в URL может изменяться, т.е. могут переименовываться поля, удаляться или добавляться новые. Нужно поддержать возможность миграции на новую схему.
При изменении URL может происходить замена текущей истории или добавлении в историю нового URL. При добавлении URL в историю появляется возможность управлять историей через браузерные кнопки вперед/назад. Это удобно для пользователя, но добавляет сложность для разработки, т.к. появляется два источника управления историей: через UI и браузерные кнопки вперед/назад. Например, при открытии модального окна добавляется в историю
?modalOpen=true. Теперь пользователь ожидает, что при нажатии на браузерную кнопку назад закроет окно.https://nuqs.47ng.com/blog/beware-the-url-type-safety-iceberg
nuqs.dev
Beware The URL Type-Safety Iceberg | nuqs
Type-safe URL state is only the visible part. There are more dangers below.
👍11❤1
Реактивность – это легко
Стандартный useContext заставляет обновляться все компоненты-потребители, даже если им не нужна изменившаяся часть состояния. Это приводит к лишним ре-рендерам, особенно в больших компонентах вроде таблиц или списков.
Автор статьи столкнулся с этим в MUI X Data Grid: клик по одной ячейке вызывал ре-рендер всех остальных. Решение — точечная подписка через селекторы
Вместо того, чтобы хранить состояние в useState и передавать его через Context, можно использовать внешний Store и специальный хук useSelector. Идея проста:
🔴 Store — это обычный класс, который хранит состояние, умеет подписывать на обновления (subscribe) и уведомлять подписчиков, когда данные изменились (update). Он живёт вне рендера React.
🔴
Хук подписывается на store и вызывает локальный ре-рендер только тогда, когда возвращаемое селектором значение изменилось.
Пример кода:
Такой подход позволяет обновлять только те компоненты, чьи данные действительно изменились, и часто избавляет от необходимости оборачивать всё в React.iss.onemo.
https://romgrk.com/posts/reactivity-is-easy/
Стандартный useContext заставляет обновляться все компоненты-потребители, даже если им не нужна изменившаяся часть состояния. Это приводит к лишним ре-рендерам, особенно в больших компонентах вроде таблиц или списков.
Автор статьи столкнулся с этим в MUI X Data Grid: клик по одной ячейке вызывал ре-рендер всех остальных. Решение — точечная подписка через селекторы
Вместо того, чтобы хранить состояние в useState и передавать его через Context, можно использовать внешний Store и специальный хук useSelector. Идея проста:
useSelector(store, selectorFn) — кастомный хук, который принимает store и функцию-селектор. Селектор — это функция, которая из всего объекта состояния достает только нужный компонентa фрагмент данных (например, `state => state.focus === index`).Хук подписывается на store и вызывает локальный ре-рендер только тогда, когда возвращаемое селектором значение изменилось.
Пример кода:
const Context = createContext();
export function Grid() {
const [store] = useState(() => new Store({ focus: 0 }));
return (
<Context.Provider value={store}>
{Array.from({ length: 50 }).map((_, i) => (
<Cell index={i} />
))}
</Context.Provider>
);
}
const selectors = {
isFocus: (state, index) => state.focus === index,
};
function Cell({ index }) {
const store = useContext(Context);
const focus = useSelector(store, selectors.isFocus, index);
return (
<button
ref={ref}
onClick={() => store.update({ ...store.state, focus: index })}
className={clsx({ focus })}
>
{index}
</button>
);
};
Такой подход позволяет обновлять только те компоненты, чьи данные действительно изменились, и часто избавляет от необходимости оборачивать всё в React.iss.onemo.
https://romgrk.com/posts/reactivity-is-easy/
Please open Telegram to view this post
VIEW IN TELEGRAM
Romgrk
Reactivity is easy
romgrk's personal blog
👎18👍5❤1