Введение
В одном переданном проекте на NextJs и typescript, попалась “интересная” ошибка при использовании библиотеки react-svg-worldmap. Для решения ошибки, пришлось обращаться к разработчику библиотеки.
О библиотеке react-svg-worldmap
Данная библиотека - github, используется для отображения карты мира, и как я понял в основном используется для вывода статистики. У нее 1049 скачиваний в неделю NPM
В основном пропсе data данной библиотеки ожидается массив - страна и число, для подсветки страны и вывода данных при наведении
// Тип данных принимаемых в пропс data
type DataItem = {
country: ISOCode;
value: number;
};
// Передаваемые данные в пропс data
const data = [
{country: 'cn', value: 1389618778}, // china
{country: 'in', value: 1311559204}, // india
{country: 'us', value: 331883986}, // united states
{country: 'id', value: 264935824}, // indonesia
{country: 'pk', value: 210797836}, // pakistan
{country: 'br', value: 210301591}, // brazil
{country: 'ng', value: 208679114}, // nigeria
{country: 'bd', value: 161062905}, // bangladesh
{country: 'ru', value: 141944641}, // russia
{country: 'mx', value: 127318112}, // mexico
];
Проект не билдится локально, но работает на сервере
В моем случае, в проекте требовалось выводить: Название страны, и текст. Предыдущий разработчик решил данное требование довольно оригинально просто, напрямую передав в пропс data - в массиве: название страны и текст. И на сервере, при наведении - успешно выводил Название страны и текст.
const data = [
{country: 'cn', value: 'Густонаселенная страна'}, // china
{country: 'in', value: 'Слоны' }, // india
{country: 'us', value: 'Кремниевая долина'}, // united states
];
Но у меня после скачивания из репозитория, и развертывания проект не билдился, выдавая ошибку, что в пропс data - переданы некорректные данные. Что логично - так как в массиве должно быть - страна (тип string) и число (тип number)
npm run build
Failed to compile.
./src/components/templates/map/component.tsx:51:29
Type error: Type '{ country: string; value: string; }[]' is not assignable to type 'IData[]'.
Type '{ country: string; value: string; }' is not assignable to type 'IData'.
Types of property 'value' are incompatible.
Type 'string' is not assignable to type 'number'.
title=""
size="xl"
data={translation.data}
^
valuePrefix=":"
tooltipBgColor="white"
tooltipTextColor="blue"
В React/NextJs новичок. И хотя понимаю ошибку - что переданный параметр использует неверный тип, не понимал, как ранее проект билдился и работал на сервере.
Прочитал документацию библиотеки, ясно вижу, что ожидаются данные в формате - страна, число. В проекте передаются некорректные данные, но тогда почему проект успешно билдился?
После поисков, я был удивлен понял - предыдущий разработчик, после установки, менял в коде библиотеки, в папке node_modules/react-svg-worldmap/dist - принимаемый тип для второго параметра - с number на string. После чего билд проходил без ошибок.
// node_modules\\react-svg-worldmap\\dist\\WorldMap.d.ts
interface IData {
country: string;
value: string; // number;
}
Полагаю, что разработчик до меня, сперва пытался сделать правильно. Но пошел по легкому пути, библиотека проста и в примерах использовалась для вывода статистики. Поэтому применил подобный угадайкак способ.
Теперь понимая почему проект не билдился, получил ситуацию:
что менять код в скомпилированной библиотеки в папке dist - не вариант (wrong way).
Использовать другую библиотеку - нежелательно.
Решать задачу по выводу названию страны и текста при наведении - надо.
Подумал, что точно кто-то еще сталкивался с подобной проблемой при использовании данной библиотеки, и наверняка другие разработчики справились. И тогда обратился к Вселенскому разуму написал issue запрос к разработчику библиотеки, с предложением добавить дополнительное поле, для возможности добавлять текст или просьбой подсказать способ вывода текста в подсказке при наведении.
К своему удивлению, довольно быстро (через пару часов) получил ответ, что уже существует параметр tooltipTextFunction
, указали прямую ссылку на документацию с примером https://yanivam.github.io/react-svg-worldmap/examples/localization . За что им очень благодарен. Сам я на эту документацию не наткнулся, т.к читал только код в репозитарии (к стыду, я затем нашел что и там все же был указан этот пропс, но я проглядел).
Решение, которое я использовал
В моем случае данные с нужным текстом подтягивались из json файла, на разных языках, поэтому их требовалось предварительно заносить в массив в нужном формате.
// файл с переводом src\\locales\\ru.ts
const data = [
{country: 'cn', value: 1389618778}, // china
{country: 'in', value: 1311559204}, // india
{country: 'us', value: 331883986}, // united states
];
const dataTranslation= [
{country: 'cn', value: 'Густонаселенная страна'}, // china
{country: 'in', value: 'Слоны' }, // india
{country: 'us', value: 'Кремниевая долина'}, // united states
];
// файл ./src/components/templates/map/component.tsx
// заносим текст с переводом в массив
let localizedArray = []
for (var val of translation.dataTranslation) {
localizedArray.push([val.country, val.value])
}
const localizedCountryDictionary: Map<string, Array<string>> = new Map(localizedArray);
// возвращаем результат локализации // localization callback
const getLocalizedText = (countryCode, countryValue, prefix, suffix) => {
const localizedCountryName = localizedCountryDictionary.has(
countryValue.toLowerCase(),
) ? localizedCountryDictionary.get(countryValue.toLowerCase()) : 'Unknown';
const russianTranlation = countryCode + ': ' + localizedCountryName
return russianTranlation;
};
// код компонента с параметром
<Component
title=""
size="xl"
data={translation.data}
valuePrefix=":"
tooltipBgColor="white"
tooltipTextColor="blue"
tooltipTextFunction={getLocalizedText}
/>
Суть решения, в том что в передаваемом props data - передаются корректные данные в формате - Страна, число. Затем в зависимости от страны, по коду страны выводится подсказка.
А подсказка выводится, через пропс tooltipTextFunction
и getLocalizedText которая предварительно берет данные из файла требуемой локали и выводит в формате string.
Само решение было на виду - причем указано в документации, но я не видел, так как рассматривал в контексте - передаю в props data - страну и текст, хочу получить подсказку с текстом. Вместо, задача выводить в подсказке при наведении на страну требуемый текст.
Выводы:
Если используется костыль - указывать в комментарии, чтобы не тратить время на поиск ошибки. Навряд ли легко догадаться, что то кто-то меняет код в папке dist библиотеки после установки.
Рассматривать в контексте - какая задача стоит, и как решить задачу. А не “как вылечить эту ошибку”.
На том конце гитхаба - разработчики библиотек, участники проекта это живые люди. Они существуют, и могут подсказать. В этом сила комьюнити.
Рассматривать ошибку - в контексте, как решить задачу, а не избавиться от ошибки.
Спасибо за то, что дочитали. Надеюсь пригодится и натолкнет на мысли.