React 16 & Context decorators

Development13 apr 2018

С обновлением React до 16 версии мы получили новый вид контекста, на замену старому. Теперь это не мутное API, как было раньше, а утверждённый вариант, с которым можно смело в бой. В чём же ключевые различия?

В итоге послевкусие специфическое. С одной стороны 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;
};

Забирайте кому надо ;)