Введение

В одном переданном проекте на 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 библиотеки после установки.

  • Рассматривать в контексте - какая задача стоит, и как решить задачу. А не “как вылечить эту ошибку”.

  • На том конце гитхаба - разработчики библиотек, участники проекта это живые люди. Они существуют, и могут подсказать. В этом сила комьюнити.

  • Рассматривать ошибку - в контексте, как решить задачу, а не избавиться от ошибки.

Спасибо за то, что дочитали. Надеюсь пригодится и натолкнет на мысли.

Комментарии (1)


  1. skeevy
    04.02.2022 15:11
    +1

    1) 1k скачиваний крайне мало

    2) почему не https://www.npmjs.com/package/react-leaflet ? Тут хотя-бы ~200к скачиваний

    3) как-то странно, по сути статья сводится к тому, что кто-то изменил руками либу в node_modules и рассуждения вокруг этого? Это не то, что костыль, на это нормативной лексики недостаточно