{"id":28916,"date":"2025-12-30T09:38:27","date_gmt":"2025-12-30T09:38:27","guid":{"rendered":"urn:uuid:1d0c8ff4-5a8f-48e2-be12-204126bcda3b"},"modified":"2026-01-13T12:05:57","modified_gmt":"2026-01-13T12:05:57","slug":"building-an-economic-blocs-map-with-highcharts-react","status":"publish","type":"post","link":"https:\/\/www.highcharts.com\/blog\/tutorials\/building-an-economic-blocs-map-with-highcharts-react\/","title":{"rendered":"Building an Economic Blocs Map with Highcharts React"},"content":{"rendered":"\n<p>Highcharts has released a new React integration that makes working with data visualizations more straightforward. The new <a href=\"https:\/\/www.npmjs.com\/package\/@highcharts\/react\" target=\"_blank\">@highcharts\/react<\/a> package offers improved component integration, full ESM support, and an API that aligns better with React patterns.<\/p>\n\n\n\n<p>In this tutorial, I will walk you through building an interactive map of all economic blocs and their member countries, a practical example that demonstrates how the new integration works. If you haven&#8217;t migrated to the new Highcharts React yet, I invite you to take a look at <a href=\"https:\/\/www.highcharts.com\/blog\/news\/how-to-migrate-to-the-new-highcharts-for-react\/\" target=\"_blank\">this short article on how to migrate to the new Highcharts for React<\/a>.<\/p>\n\n\n\n<p>Let&#8217;s get started&nbsp;\ud83d\ude42 <\/p>\n\n\n\n<p>What the app does<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Pick an economic bloc from a custom dropdown.<\/li>\n\n\n\n<li>Highlights member countries on a world map.<\/li>\n\n\n\n<li>Shows quick stats: GDP, population, founding year, member count.<\/li>\n\n<\/ul>\n<!-- \/wp:post-content -->\n\n<!-- wp:paragraph -->\n<p>What you need to achieve this app&nbsp;<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:list -->\n<ul class=\"wp-block-list\"><!-- wp:list-item -->\n<li>React 18<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li>Highcharts 12+ with @highcharts\/react<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li>Topojson fallback: @highcharts\/map-collection\/custom\/world.topo.json<\/li>\n<!-- \/wp:list-item --><\/ul>\n<!-- \/wp:list -->\n\n<!-- wp:paragraph -->\n<p>Feel free to try it out:<br><em>Link to the <a href=\"https:\/\/codesandbox.io\/p\/github\/mekhatria\/economic-blocs-map\/main\" target=\"_blank\">demo CodeSandbox<\/a><\/em><br><br><\/p>\n<!-- \/wp:paragraph -->\n<iframe \n  src=\"https:\/\/codesandbox.io\/embed\/github\/mekhatria\/economic-blocs-map\/main?view=preview&#038;hidenavigation=1&#038;hidedevtools=1\"\n  style=\"width:100%; height:780px; border:0; border-radius: 4px; overflow:hidden;\"\n  title=\"Economic Blocs Map\"\n  sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n><\/iframe>\n<!-- wp:paragraph -->\n<p>The architecture is very straight forward:<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>App<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>\u251c\u2500 BlocDropdown (uses useOutsideClick)<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>\u251c\u2500 BlocInfo<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>\u2502&nbsp; \u2514\u2500 StatCard<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>\u2514\u2500 MapChart<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>Here is some information about the elements:<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:list -->\n<ul class=\"wp-block-list\"><!-- wp:list-item -->\n<li>App: holds selected bloc, computes series data, coordinates children.<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li>BlocDropdown: custom selector with outside-click close.<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li>BlocInfo: bloc stats panel using StatCard.<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li>MapChart: Highcharts map renderer.<\/li>\n<!-- \/wp:list-item --><\/ul>\n<!-- \/wp:list -->\n\n<!-- wp:paragraph -->\n<p>Before I dive into the code, let&#8217;s understand what makes the new @highcharts\/react way better than the old one, this will help you follow along more easily.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:heading {\"level\":3} -->\n<h3 class=\"wp-block-heading\"><strong>Understanding the new @highcharts\/react approach<\/strong><\/h3>\n<!-- \/wp:heading -->\n\n<!-- wp:paragraph -->\n<p>The new @highcharts\/react package brings two major improvements over the old highcharts-react-official:<br><strong>1. Component-based &amp; Declarative<\/strong> Instead of passing a <code>highcharts<\/code> prop everywhere, you import specialized components like <code>MapsChart<\/code> and <code>MapSeries<\/code>. Your React code stays clean and declarative:<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:code -->\n<pre class=\"wp-block-code\"><code>&lt;MapsChart chartConstructor=\"mapChart\" options={mapOptions}>\n\n\u00a0\u00a0&lt;MapSeries options={{ mapData, data: seriesData, joinBy: 'hc-key' }} \/>\n\n&lt;\/MapsChart><\/code><\/pre>\n<!-- \/wp:code -->\n\n<!-- wp:paragraph -->\n<p><strong>2. One-time Initialization<\/strong> You initialize Highcharts modules once in a setup file, then every component in your app just works, no repeated configuration.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:heading {\"level\":3} -->\n<h3 class=\"wp-block-heading\"><strong>Setting up Highcharts once<\/strong><\/h3>\n<!-- \/wp:heading -->\n\n<!-- wp:paragraph -->\n<p>The key to making maps work throughout your app is a one-time setup file. Create <code>src\/lib\/highchartsSetup.js<\/code>:<\/p>\n\n<!-- wp:code -->\n<pre class=\"wp-block-code\"><code>import Highcharts from \u2018highcharts\u2019;\nimport mapModule from \u2018highcharts\/modules\/map.js\u2019;\nimport { setHighcharts } from \u2018@highcharts\/react\u2019;\nimport worldMap from \u2018@highcharts\/map-collection\/custom\/world.topo.json\u2019;\n\/\/ Initialize the map module\nconst mapFactory = mapModule && (mapModule.default || mapModule);\nif (typeof mapFactory === \u2018function\u2019) mapFactory(Highcharts);\n\/\/ Register the bundled topojson for offline fallback\nHighcharts.maps = Highcharts.maps || {};\nHighcharts.maps[\u2018custom\/world\u2019] = worldMap;\n\/\/ Hand the configured instance to @highcharts\/react\nsetHighcharts(Highcharts);\nexport { Highcharts, worldMap };<\/code><\/pre>\n<!-- \/wp:code -->\n\n\n\n\n<!-- wp:paragraph -->\n<p><strong>What&#8217;s happening here?<\/strong><\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:list {\"ordered\":true} -->\n<ol class=\"wp-block-list\"><!-- wp:list-item -->\n<li>Import Highcharts and the map module<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li>Run the map module to add map support to Highcharts<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li>Bundle the world topojson from <code>@highcharts\/map-collectio<\/code>n and register it under <code>'custom\/world'<\/code><\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li>Call <code>setHighcharts()<\/code> to give this configured instance to all <code>@highcharts\/react<\/code> components<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li>Export everything so other files can use it if needed<\/li>\n<!-- \/wp:list-item --><\/ol>\n<!-- \/wp:list -->\n\n<!-- wp:paragraph -->\n<p>This setup runs once when your app loads. After that, every <code>MapsChart<\/code> and <code>MapSeries<\/code> component has map support and topojson baked in. No need to pass <code>Highcharts<\/code> as a prop or repeat this configuration.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p><strong>Bonus<\/strong><\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p>I am enabling Offline Fallback. By bundling the topojson, the map works even when the CDN is unreachable. The <code>useMapData<\/code> hook (which you will see in the data flow) will try fetching the latest topojson from the Highcharts CDN first, but if that fails, it falls back to this bundled version. The topojson itself lives at <code>node_modules\/@highcharts\/map-collection\/custom\/world.topo.json<\/code>.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:heading {\"level\":3} -->\n<h3 class=\"wp-block-heading\"><strong>Data flow overview<\/strong><\/h3>\n<!-- \/wp:heading -->\n\n<!-- wp:paragraph -->\n<p>Now that setup is handled, let&#8217;s see how data moves through the app:<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:list {\"ordered\":true} -->\n<ol class=\"wp-block-list\"><!-- wp:list-item -->\n<li><strong>Economic blocs data<\/strong> lives in <code>src\/economicBlocs.js<\/code> (name, GDP, population, founded year, ISO country codes)<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><strong>App component<\/strong> holds the selected bloc and computes <code>seriesData<\/code> (which countries to highlight)<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><strong>useMapData hook<\/strong> fetches topojson from the Highcharts CDN with the bundled JSON as fallback<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><strong>MapChart<\/strong> receives <code>mapData<\/code> and <code>seriesData<\/code>, then renders the map using <code>MapsChart<\/code> and <code>MapSeries<\/code><\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><strong>BlocInfo<\/strong> displays four StatCard components showing GDP, population, founding year, and member count<\/li>\n<!-- \/wp:list-item --><\/ol>\n<!-- \/wp:list -->\n\n<!-- wp:paragraph -->\n<p>With this flow in mind, let&#8217;s look at the heart of the app: the MapChart component.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:heading {\"level\":3} -->\n<h3 class=\"wp-block-heading\"><strong>Building MapChart.jsx<\/strong><\/h3>\n<!-- \/wp:heading -->\n\n<!-- wp:paragraph -->\n<p>MapChart is where the React app actually renders the map using <code>@highcharts\/react<\/code>. Let&#8217;s break it down step by step.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:paragraph -->\n<p><strong>Import the map-specific React wrappers:<\/strong><\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:code -->\n<pre class=\"wp-block-code\"><code>const mapOptions = {\n  chart: { \n    backgroundColor: \u2018#1a1a1a\u2019, \n    animation: false \n  },\n  tooltip: {\n    formatter: function() { return this.point.name; },\n    backgroundColor: \u2018#1a1a1a\u2019,\n    borderColor: \u2018#00bcd4\u2019,\n    style: { color: \u2018white\u2019 }\n  },\n  colorAxis: {\n    min: 0, \n    max: 1,\n    stops: [[0, \u2018#2a2a2a\u2019], [1, \u2018#ff6b6b\u2019]],\n    visible: false\n  }\n};<\/code><\/pre>\n<!-- \/wp:code -->\n\n\n<!-- wp:paragraph -->\n<p><strong>Build the component:<\/strong> The component expects <code>mapData<\/code> (topojson) and <code>seriesData<\/code> (the selected bloc&#8217;s countries):<\/p>\n<!-- \/wp:paragraph -->\n\n\n<!-- wp:code -->\n<pre class=\"wp-block-code\"><code>function MapChart({ mapData, seriesData }) {\n  return (\n    &lt;div style={{ maxWidth: '800px', margin: '20px auto', padding: '0 20px' }}&gt;\n      &lt;MapsChart chartConstructor=\"mapChart\" options={mapOptions}&gt;\n        &lt;MapSeries options={{\n          mapData,\n          name: 'Countries',\n          data: seriesData,\n          joinBy: 'hc-key',\n          nullColor: '#2a2a2a',\n          borderColor: '#555555',\n          borderWidth: 1\n        }} \/&gt;\n      &lt;\/MapsChart&gt;\n    &lt;\/div&gt;\n  );\n}<\/code><\/pre>\n<!-- \/wp:code -->\n\n\n\n<!-- wp:paragraph -->\n<p><strong>How it works:<\/strong><\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:list -->\n<ul class=\"wp-block-list\"><!-- wp:list-item -->\n<li><code>&lt;MapsChart chartConstructor=\"mapChart\" options={mapOptions}&gt;<\/code> sets up the map chart container with our dark theme and tooltip<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li>The nested <mapseries> <\/mapseries><code>&lt;MapSeries&gt;<\/code> <mapseries>component does the heavy lifting:<\/mapseries><!-- wp:list -->\n<ul class=\"wp-block-list\"><!-- wp:list-item -->\n<li><code>mapData<\/code>: the topojson defining country boundaries<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><code>data<\/code>: the array of highlighted countries (seriesData)<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><code>joinBy: 'hc-key'<\/code>: matches our data to the topojson using Highcharts country keys<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><code>nullColor<\/code>: color for unselected countries<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><code>borderColor\/borderWidth<\/code>: country borders<\/li>\n<!-- \/wp:list-item --><\/ul>\n<!-- \/wp:list --><\/li>\n<!-- \/wp:list-item --><\/ul>\n<!-- \/wp:list -->\n\n<!-- wp:paragraph -->\n<p>Because I ran the setup file earlier, this component has everything it needs. No <code>highcharts<\/code> prop, no module initialization, just clean, declarative React.<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:heading {\"level\":3} -->\n<h3 class=\"wp-block-heading\"><strong>Wrapping up<\/strong><\/h3>\n<!-- \/wp:heading -->\n\n<!-- wp:paragraph -->\n<p>You now know how to create an interactive map with the new @highcharts\/react. The key takeaways:<\/p>\n<!-- \/wp:paragraph -->\n\n<!-- wp:list {\"ordered\":true} -->\n<ol class=\"wp-block-list\"><!-- wp:list-item -->\n<li><strong>Set up once<\/strong> in <code>highchartsSetup.js<\/code> with modules and topojson<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><strong>Use components<\/strong> like <code>MapsChart<\/code> and <code>MapSeries<\/code> for declarative rendering<\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><strong>Bundle topojson<\/strong> for offline fallback via <code>@highcharts\/map-collection<\/code><\/li>\n<!-- \/wp:list-item -->\n\n<!-- wp:list-item -->\n<li><strong>Keep it simple<\/strong> let the setup file handle initialization, and let your components focus on rendering<\/li>\n<!-- \/wp:list-item --><\/ol>\n<!-- \/wp:list -->\n\n<!-- wp:paragraph -->\n<p>The new <code>@highcharts\/react<\/code> makes maps easier to work with in React apps.<\/p>\n<!-- \/wp:paragraph -->\n","protected":false},"excerpt":{"rendered":"<p>Highcharts has released a new React integration that makes working with data visualizations more straightforward. The new @highcharts\/react package offers improved component integration, full ESM support, and an API that aligns better with React patterns. In this tutorial, I will walk you through building an interactive map of all economic blocs and their member countries, [&hellip;]<\/p>\n","protected":false},"author":32,"featured_media":28925,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"meta_title":"Building Interactive Maps with Highcharts React Tutorial","meta_description":"Complete guide to building interactive maps using Highcharts React. Create dynamic visualizations with topojson, custom components, and offline fallback support.","hc_selected_options":[],"footnotes":""},"categories":[210],"tags":[876,1031,824],"coauthors":[699],"class_list":["post-28916","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-highcharts-maps","tag-javascript","tag-react"],"_links":{"self":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/28916","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/users\/32"}],"replies":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/comments?post=28916"}],"version-history":[{"count":3,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/28916\/revisions"}],"predecessor-version":[{"id":28959,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/28916\/revisions\/28959"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media\/28925"}],"wp:attachment":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media?parent=28916"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/categories?post=28916"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/tags?post=28916"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/coauthors?post=28916"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}