Поиск по метке: JSX
React 16 & Context decorators
С обновлением React до 16 версии мы получили новый вид контекста, на замену старому. Теперь это не мутное API, как было раньше, а утверждённый вариант, с которым можно смело в бой. В чём же ключевые различия?
- Старый вариант был многословным. Новый вариант компактнее.
- Старый вариант не обновлял связанные с контекстом компоненты при изменении контекста. По сути контекст должен был быть имутабельным. Новый вариант обновляет связанные с ним компоненты.
- Старый вариант можно было использовать в любом методе компонента. Новый только в render-е.
- Старый вариант не имел пенальти по производительности и не требовал использования HOC-ов, не увеличивал иерархию древа. Новый вариант всё это делает. Скажем для connect-а из redux-а потребуется аж 2 дополнительных уровня иерархии.
- Старый вариант был оформлен в виде static полей класса, новый вариант в виде function as tag content. И то и другое слегка уродливо. Или не слегка. JSX в целом страшненький. А тут...
В итоге послевкусие специфическое. С одной стороны API хотя бы устаканили. С другой стороны сделали его каким-то очень неудобным и вообще кривоватым. Такое впечатление возникает в целом, глядя на новые возможности из 16+. Но тут я остановлюсь на работе с контекстом.
Писать вот так:
render()
{
return <Consumer>{arg1 =>
<Consumer2>{arg2 =>
<div>/* some code with them */</div>
}</Consumer2>
}</Consumer>
}
… невыносимо. Хочется удобства. В итоге это вылилось в такой вариант:
@renderContext('arg1', 'arg2')
render(arg1, arg2)
{
return <div>/* some code with them */</div>;
}
По сути я воспользовался декораторами из ES7, которые пока под некоторым вопросом. Но т.к. JSX в стандарте тоже нет, то плевать. Что делает данный декоратор? Он оборачивает метод render обёртками из кода выше. Но делает это автоматически. А в исходный render метод передаёт все контексты как аргументы функции в том же порядке.
Никакой магии в этом нет и все эти обёртки над обёртками никуда не испарились, но теперь хотя бы скрыты с глаз долой. Помимо прочего я написал ещё несколько декораторов. Один для <Provider/>-ов, один для HOC, один для удобтва i18n. Чувствую в декораторы затянет меня с головой. Ух злая эта штука. Это не к добру :)
Сам декоратор устроен вот так:
const renderContext = (...keys) =>
function(target, methodName, descriptor)
{
const render = descriptor.value;
descriptor.value = keys
.map(key => list[key].Consumer)
.reverse()
.reduce((inner, Consumer) =>
{
return function(...args)
{
return <Consumer>
{arg => inner.call(this, ...args, arg)}
</Consumer>;
};
}, render);
return descriptor;
};
Забирайте кому надо ;)
JSX и вветвления ― jsx-control-statements
Одна из раздражающих меня в React вещей, это помесь XML и JS синтаксиса. И ладно бы в одном файле, но, блин, даже в одном блоке. Сочетания XML и конструкций вроде {arr.map(arr => { очень сильно бьют, как по читаемости, так и по глазам в целом. К счастью, есть возможность этого избежать, используя jsx-control-statements. Т.к. его внедрение оказалось делом не совсем тривиальным, я решил написать об этому небольшой очерк.
Для начала, что нам даёт этот плагин?
<If condition={anyCondition}>...</If>
// вместо
{anyCondition && ...}
А также
<For each="el" index="key" of={arr}>...</For>
// вместо
{arr.map((el, key) => ...}
Т.е. XML-like конструкции, похожие на соответствующие им из XSLT (только более компактные). Также там есть ещё <Choice/> для switch-ей.
Ok, а как оно работает? Оно городит новые DOM-элементы? Нет. Оно ещё на уровне babel-я трансформируется в те самые && и .map. Т.е. это синтаксический сахар для эстетов. Ok, как подключить?
- npm i jsx-control-statements
- в настройки babel-я в plugins добавляем "jsx-control-statements"
Всё, работает. А как насчёт lint-инга? Оказалось, что тут тоже всё схвачено (для eslint), но нужно немного понастраивать:
- npm i eslint-plugin-jsx-control-statements
- в настройках eslint
- в plugins добавляем jsx-control-statements
- в extends добавляем jsx-control-statements
Теперь никаких неудобств. Проблем с подстветкой синтаксиса тоже никаких (если у вас вообще JSX нормально отображается, конечно).