1---
2title: Use third-party native libraries in Expo
3description: Learn how to create a simple wrapper around two separate native libraries using Expo Modules.
4---
5
6import ImageSpotlight from '~/components/plugins/ImageSpotlight';
7import { Terminal } from '~/ui/components/Snippet';
8import { Step } from '~/ui/components/Step';
9import { BoxLink } from '~/ui/components/BoxLink';
10import { BookOpen02Icon, Grid01Icon } from '@expo/styleguide-icons';
11
12Expo modules make it possible to easily use native, external libraries built for Android and iOS in React Native projects.
13This tutorial focuses on utilizing the Expo Modules API to create radial charts using two similar libraries accessible on both native platforms.
14
15- [MPAndroidChart by PhilJay](https://github.com/PhilJay/MPAndroidChart)
16- [Charts by Daniel Cohen Gindi](https://github.com/danielgindi/Charts)
17
18The iOS library is inspired by the Android library, so they both have a very similar API and functionality.
19This makes them a good example for this tutorial.
20
21<Step label="1">
22## Create a new module
23
24You can start by creating a new empty Expo module. We're creating a separate project for this tutorial. However, you can create a new module inside your existing project.
25
26### Start with a new project
27
28To create an empty Expo module that can be published on npm and utilized in any Expo application, run the following command:
29
30<Terminal cmd={['$ npx create-expo-module expo-radial-chart']} />
31
32> **Tip**: If you aren't going to ship this library, press <kbd>return</kbd> for all of the prompts to accept the default values in the terminal window.
33
34Now, open the newly created `expo-radial-chart` directory to start editing the native code.
35
36### Start with an existing project
37
38Alternatively, you can use the new module as a view inside the existing project. Run the following command in your project's directory:
39
40<Terminal cmd={['$ npx create-expo-module --local expo-radial-chart']} />
41
42Now, open the newly created `modules/expo-radial-chart` directory to start editing the native code.
43
44</Step>
45
46<Step label="2">
47
48## Run the example project
49
50To verify that everything is functioning correctly, let's run the example project. In the terminal window, start the TypeScript compiler to watch for changes and rebuild the module JavaScript.
51
52<Terminal
53  cmdCopy="npm run build"
54  cmd={[
55    '# Run this in the root of the project to start the TypeScript compiler',
56    '$ npm run build',
57  ]}
58/>
59
60In another terminal window, compile and run the example app:
61
62<Terminal
63  cmdCopy="cd example && npx expo run:ios"
64  cmd={[
65    '$ cd example',
66    '# Run the example app on iOS',
67    '$ npx expo run:ios',
68    '# Run the example app on Android',
69    '$ npx expo run:android',
70  ]}
71/>
72
73</Step>
74
75<Step label="3">
76## Add native dependencies
77
78Now, add the native dependencies to the module by editing the **android/build.gradle** and **ios/ExpoRadialChart.podspec** files:
79
80```diff android/build.grade
81dependencies {
82  implementation project(':expo-modules-core')
83  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
84+ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
85}
86```
87
88```diff ios/ExpoRadialChart.podspec
89    s.static_framework = true
90
91    s.dependency 'ExpoModulesCore'
92+   s.dependency 'Charts', '~> 4.1.0'
93
94    # Swift/Objective-C compatibility
95```
96
97</Step>
98
99<Step label="4">
100## Define an API
101
102To use the module in the app without mistakes, define the types for the props. This module accepts a list of series &mdash; each with a color and a percentage value.
103
104```ts src/ExpoRadialChart.types.ts
105import { ViewStyle } from 'react-native/types';
106
107export type ChangeEventPayload = {
108  value: string;
109};
110
111type Series = {
112  color: string;
113  percentage: number;
114};
115
116export type ExpoRadialChartViewProps = {
117  style?: ViewStyle;
118  data: Series[];
119};
120```
121
122Since we won't implement the module on the web in this example, let's replace the **src/ExpoRadialChartView.web.tsx** file:
123
124```tsx src/ExpoRadialChartView.web.tsx
125import * as React from 'react';
126
127export default function ExpoRadialChartView() {
128  return <div>Not implemented</div>;
129}
130```
131
132</Step>
133
134<Step label="5">
135## Implement the module on Android
136
137Now you can implement the native functionality by editing the placeholder files with the following changes:
138
139- Create a `PieChart` instance and set its `layoutParams` to match the parent view. Then, add it to the view hierarchy using the `addView` function.
140- Define a `setChartData` function that accepts a list of `Series` objects. You can iterate over the list, create a `PieEntry` for each series and store the colors in a separate list. Then, create a `PieDataSet`, use it to create a `PieData` object, and set it as data on the `PieChart` instance.
141
142```kotlin android/src/main/java/expo/modules/radialchart/ExpoRadialChartView.kt
143package expo.modules.radialchart
144
145import android.content.Context
146import android.graphics.Color
147import androidx.annotation.ColorInt
148import com.github.mikephil.charting.charts.PieChart
149import com.github.mikephil.charting.data.PieData
150import com.github.mikephil.charting.data.PieDataSet
151import com.github.mikephil.charting.data.PieEntry
152import expo.modules.kotlin.AppContext
153import expo.modules.kotlin.records.Field
154import expo.modules.kotlin.records.Record
155import expo.modules.kotlin.views.ExpoView
156
157
158class Series : Record {
159  @Field
160  val color: String = "#ff0000"
161
162  @Field
163  val percentage: Float = 0.0f
164}
165
166class ExpoRadialChartView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
167  internal val chartView = PieChart(context).also {
168    it.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
169    addView(it)
170  }
171
172  fun setChartData(data: ArrayList<Series>) {
173    val entries: ArrayList<PieEntry> = ArrayList()
174    val colors: ArrayList<Int> = ArrayList()
175    for (series in data) {
176      entries.add(PieEntry(series.percentage))
177      colors.add(Color.parseColor(series.color))
178    }
179    val dataSet = PieDataSet(entries, "DataSet");
180    dataSet.colors = colors;
181    val pieData = PieData(dataSet);
182    chartView.data = pieData;
183    chartView.invalidate();
184
185  }
186}
187```
188
189You also need to use the [`Prop`](/modules/module-api/#prop) function to define the `data` prop and call the native `setChartData` function when the prop changes:
190
191```kotlin android/src/main/java/expo/modules/radialchart/ExpoRadialChartModule.kt
192package expo.modules.radialchart
193
194import expo.modules.kotlin.modules.Module
195import expo.modules.kotlin.modules.ModuleDefinition
196
197class ExpoRadialChartModule : Module() {
198  override fun definition() = ModuleDefinition {
199    Name("ExpoRadialChart")
200
201    View(ExpoRadialChartView::class) {
202      Prop("data") { view: ExpoRadialChartView, prop: ArrayList<Series> ->
203        view.setChartData(prop);
204      }
205    }
206  }
207}
208```
209
210</Step>
211
212<Step label="6">
213## Implement the module on iOS
214
215Now you can implement the native functionality by editing the placeholder files with the following changes:
216
217- Create a new `PieChartView` instance and use the `addSubview` function to add it to the view hierarchy.
218- Set the `clipsToBounds` property and override the `layoutSubviews` function to make sure the chart view is always the same size as the parent view.
219- Finally, create a `setChartData` function that accepts a list of series, creates a `PieChartDataSet` instance with the data, and assigns it to the `data` property of the `PieChartView` instance.
220
221```swift ios/ExpoRadialChartView.swift
222import ExpoModulesCore
223import Charts
224
225struct Series: Record {
226  @Field
227  var color: UIColor = UIColor.black
228
229  @Field
230  var percentage: Double = 0
231}
232
233class ExpoRadialChartView: ExpoView {
234  let chartView = PieChartView()
235
236  required init(appContext: AppContext? = nil) {
237    super.init(appContext: appContext)
238    clipsToBounds = true
239    addSubview(chartView)
240  }
241
242  override func layoutSubviews() {
243    chartView.frame = bounds
244  }
245
246  func setChartData(data: [Series]) {
247    let set1 = PieChartDataSet(entries: data.map({ (series: Series) -> PieChartDataEntry in
248      return PieChartDataEntry(value: series.percentage)
249    }))
250    set1.colors = data.map({ (series: Series) -> UIColor in
251      return series.color
252    })
253    let chartData: PieChartData = [set1]
254    chartView.data = chartData
255  }
256}
257```
258
259You also need to use the [`Prop`](/modules/module-api/#prop) function to define the `data` prop and call the native `setChartData` function when the prop changes:
260
261```swift ios/ExpoRadialChartModule.swift
262import ExpoModulesCore
263
264public class ExpoRadialChartModule: Module {
265  public func definition() -> ModuleDefinition {
266    Name("ExpoRadialChart")
267
268    View(ExpoRadialChartView.self) {
269      Prop("data") { (view: ExpoRadialChartView, prop: [Series]) in
270        view.setChartData(data: prop)
271      }
272    }
273  }
274}
275```
276
277</Step>
278
279<Step label="7">
280
281## Write an example app to use the module
282
283You can update the app inside the **example** directory to test the module. Use the `ExpoRadialChartView` component to render a pie chart with three slices:
284
285```tsx example/App.tsx
286import { ExpoRadialChartView } from 'expo-radial-chart';
287import { StyleSheet } from 'react-native';
288
289export default function App() {
290  return (
291    <ExpoRadialChartView
292      style={styles.container}
293      data={[
294        {
295          color: '#ff0000',
296          percentage: 0.5,
297        },
298        {
299          color: '#00ff00',
300          percentage: 0.2,
301        },
302        {
303          color: '#0000ff',
304          percentage: 0.3,
305        },
306      ]}
307    />
308  );
309}
310
311const styles = StyleSheet.create({
312  container: {
313    flex: 1,
314  },
315});
316```
317
318> **Tip**: If you created the module inside an existing application, make sure to import it directly from your **modules** directory by using a relative import: `import { ExpoRadialChartView } from '../modules/expo-radial-chart';`
319
320</Step>
321
322<Step label="8">
323## Rebuild and launch your application
324
325To make sure your app builds successfully on both platforms, rerun the build commands from step 2. After the app is successfully built on any of the platform you'll see a pie chart with three slices:
326
327<ImageSpotlight
328  src="/static/images/modules/third-party-library/result.webp"
329  alt="A PieChart module on Android and iOS"
330/>
331
332</Step>
333
334## Next steps
335
336Congratulations! You've created your first simple wrapper around two separate third-party native libraries using Expo Modules!
337
338<BoxLink
339  href="/modules/native-module-tutorial/"
340  title="Creating a native module"
341  icon="arrow-right"
342  iconType="feather"
343  iconSize={16}
344  iconColor="#000"
345/>
346<BoxLink
347  href="/modules/module-api/"
348  title="Expo Module API reference"
349  icon="arrow-right"
350  iconType="feather"
351  iconSize={16}
352  iconColor="#000"
353/>
354