{"id":17675322,"url":"https://github.com/numandev1/react-native-best-practice","last_synced_at":"2025-05-12T13:27:22.837Z","repository":{"id":208183830,"uuid":"719541091","full_name":"numandev1/react-native-best-practice","owner":"numandev1","description":"React Native best practices📚✨","archived":false,"fork":false,"pushed_at":"2023-12-30T10:11:21.000Z","size":6593,"stargazers_count":20,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-02T16:55:43.220Z","etag":null,"topics":["best","best-practices","expo","increase-performance","measure","memoization","performance","practice","practices","profiling","react-native","wdyr"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/numandev1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-11-16T11:44:29.000Z","updated_at":"2025-01-12T20:57:48.000Z","dependencies_parsed_at":"2023-12-11T06:00:26.093Z","dependency_job_id":"44086033-27fa-4697-b6d4-dc15182db524","html_url":"https://github.com/numandev1/react-native-best-practice","commit_stats":{"total_commits":13,"total_committers":1,"mean_commits":13.0,"dds":0.0,"last_synced_commit":"78428149c114149cd8b5e950f6694c12e0b42685"},"previous_names":["numandev1/react-native-best-practice","numandev1/react-native-best-practices"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numandev1%2Freact-native-best-practice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numandev1%2Freact-native-best-practice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numandev1%2Freact-native-best-practice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numandev1%2Freact-native-best-practice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/numandev1","download_url":"https://codeload.github.com/numandev1/react-native-best-practice/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253187148,"owners_count":21868070,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["best","best-practices","expo","increase-performance","measure","memoization","performance","practice","practices","profiling","react-native","wdyr"],"created_at":"2024-10-24T07:10:45.831Z","updated_at":"2025-05-12T13:27:22.817Z","avatar_url":"https://github.com/numandev1.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n \u003cimg height=\"150\" src=\"/media/logo.png\" /\u003e\n\u003c/div\u003e\n \n\u003cbr/\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![GitHub Repo stars](https://img.shields.io/badge/React_Native-20232A?style=for-the-badge\u0026logo=react\u0026logoColor=61DAFB)](#installation)\n[![GitHub Repo stars](https://img.shields.io/badge/Expo-1B1F23?style=for-the-badge\u0026logo=expo\u0026logoColor=white)](#installation)\n[![GitHub Repo stars](https://img.shields.io/static/v1?style=for-the-badge\u0026message=Discord\u0026color=5865F2\u0026logo=Discord\u0026logoColor=FFFFFF\u0026label=)](https://discord.gg/5XCGcTTazY)\n[![GitHub Repo stars](https://img.shields.io/github/stars/numandev1/react-native-best-practice?style=for-the-badge\u0026logo=github)](https://github.com/numandev1/react-native-best-practice/stargazers)\n![npm](https://img.shields.io/npm/dt/react-native-best-practice?style=for-the-badge)\n\n\u003c/div\u003e\n\n**REACT-NATIVE-BEST-PRACTICE** is a react-native best practice and a package, which provides techniques for increasing performance as well as utilities for increasing the performance of the app\n\n## Table of Contents\n\n- [Why-Did-You-Render (avoid extra rerendering)](#why-did-you-render-avoid-extra-rerendering)\n- [Memoization in React](#memoization-in-react)\n  - [Pure Components](#pure-components)\n  - [Reference equality](#reference-equality)\n  - [React](#react)\n  - [Examples](#examples)\n  - [react-native-performance](#react-native-performance)\n  - [Disclaimer](#disclaimer)\n  - [react-native-best-practice hooks and utils](#best-practices-hooks-and-utils)\n    - [Installation](#installation)\n    - [Usage](#usage)\n    - [Hooks list](#hooks-list)\n    - [Util](#util)\n- [Pro Tips](#pro-tips)\n  - [Monitor RAM, JS framerate, and UI framerate](#monitor-ram-js-framerate-and-ui-framerate)\n  - [Use Flashlist for listing](#monitor-ram-js-framerate-and-ui-framerate)\n  - [Custom Logger](#custom-logger)\n  - [State Management](#state-management)\n  - [Ref](#ref)\n  - [Native Stack](#native-stack)\n  - [Buffer](#buffer)\n  - [Storage (MMKV)](#storage-mmkv)\n  - [Image/Video Placeholders](#imagevideo-placeholders)\n  - [$ Currencies Handle](#currencies-handle)\n  - [Safearea insets](#safearea-insets)\n  - [C++ Book](#c-book)\n  - [Custom Text Component](#custom-text-component)\n  - [Big Number](#big-number)\n  - [Crypto](#crypto)\n  - [Do Measure Performance and Profiling](#do-measure-performance-and-profiling)\n  - [Remove Console.log from production app](#remove-consolelog-from-production-app)\n\n# Why-Did-You-Render (avoid extra rerendering)\n\nyou should use [why-did-you-render](https://github.com/welldone-software/why-did-you-render) which notify you about potentially avoidable re-renders.\n\n```ts\nimport React from 'react';\n\nconst useWDYR = __DEV__;\n\nif (useWDYR) {\n  const whyDidYouRender = require('@welldone-software/why-did-you-render');\n  whyDidYouRender(React, {\n    // Enable tracking in all pure components by default\n    trackAllPureComponents: true,\n    trackHooks: true,\n\n    include: [\n      // Uncomment to enable tracking in all components. Must also uncomment /^Screen/ in exclude.\n      // /.*/,\n      // Uncomment to enable tracking by displayName, e.g.:\n      // /^Components/,\n    ],\n\n    exclude: [\n      // Uncomment to enable tracking in all components\n      // /^Components/,\n    ],\n  });\n}\n```\n\nimport above file code into your app root `index.js`\n\n# Memoization in React\n\n\u003cdiv align=\"center\"\u003e\n\u003cblockquote\u003e\n  \u003ca href=\"https://react.dev/reference/react/memo\"\u003e\u003ci\u003elets you skip re-rendering a component when its props are unchanged.\u003c/i\u003e\u003c/a\u003e\n\u003c/blockquote\u003e\n\u003c/div\u003e\n\nIt's important to memoize heavy computations as well as arrays and object creations so that they don't get re-created on every render. A re-render occurs when state changes, redux dispatches some action, or when the user types into a text input (re-render for every single key press). You don't want to run a lot of operations in those renders for very obvious reasons - so no heavy filtering, no list operations, etc.\n\n## Pure Components\n\nA [Pure Component](https://reactjs.org/docs/react-api.html#reactpurecomponent) (or a `React.memo` component) does not re-render if it's props are _shallow equal_.\n\nEach variable you create in your render function will get re-allocated on each render. While this is not a problem for **value types**, this causes **reference types** to be different on every render. When you pass those variables down to **pure components** via props, they will still re-render even though the props are logically the same. Often those variables even go over the Bridge and make your app slow.\n\n## Reference equality\n\nWhen a pure component re-renders, it compares the previous props to the current props and checks if they are _shallow-equal_.\n\n### Value types\n\n**Numbers**, **strings** and **booleans** are **value types**, which means they can be _compared by value_:\n\n```js\nconst i1 = 7;\nconst i2 = 7;\nconst equal = i1 === i2; // true\n```\n\n### Reference types\n\n**Objects**, **arrays** and **functions** are **reference types**, which means they cannot be compared by their logical value, but have to be _compared by reference_:\n\n```js\nconst o1 = { x: 7 };\nconst o2 = { x: 7 };\nconst equal = o1 === o2; // false\n```\n\nReference comparisons simply compare the memory address of the variable, so only `o1 === o1` would be `true` in the above code example.\n\n\u003e 'isEqual`from`react-native-best-practice` to compare objects by actual equality, but that's not _shallow equality_ anymore.\n\n### React\n\nIf you create objects in your render function, they will be re-created on every single render. This means when you create an object in the first render, it is not _reference-equal_ to the object in the second render. For this very reason, memoization exists.\n\n- Use the `useMemo` hook to memoize arrays and objects which will keep their reference equality (and won't get re-created on each render) as long as the dependencies (second argument) stay the same. Also use `useMemo` to cache heavy computations, such as array operations, filtering, etc.\n- Use the `useCallback` hook to memoize a function.\n- If you are re creating objective but can have same values then you can use `useDeepEffect`, `useDeepCallback`, `useDeepImperativeHandle` and `useDeepLayoutEffect` from `import {useDeepEffect, ...} from 'react-native-best-practice'`\n\nIn general, function components can be optimized more easily due to the concept of [hooks](https://reactjs.org/docs/hooks-overview.html). You can however apply similar techniques for class components, just be aware that this will result in a lot more code.\n\n### React Native\n\nWhile animations and performance intensive tasks are scheduled on native threads, your entire business logic runs on a single JavaScript thread, so make sure you're doing as little work as possible there. Doing too much work on the JavaScript thread can be compared to a high ping in a video game - you can still look around smoothly, but you can't really play the game because every interaction takes too long.\n\nNative components (`\u003cView\u003e`, `\u003cText\u003e`, `\u003cImage\u003e`, `\u003cBlurhash\u003e`, ...) have to pass props to native via the bridge. They can be memoized, so React compares the props for _shallow-equality_ and only passes them over the bridge if they are different than the props from the last render. If you don't memoize correctly, you might up passing props over the bridge for every single render, causing the bridge to be very occupied. See the [Styles](#styles) example - styles will get sent over the bridge on every re-render!\n\nHere are a few examples to help you avoid doing too much work on your JavaScript thread:\n\n# Examples\n\n## Styles\n\n### Bad\n\n```jsx\nreturn \u003cView style={[styles.container, { backgroundColor: 'red' }]} /\u003e;\n```\n\n### Good\n\n```jsx\nconst style = useMemo(() =\u003e [styles.container, { backgroundColor: 'red' }], []);\nreturn \u003cView style={style} /\u003e;\n```\n\n### Exceptions\n\n- Reanimated styles from `useAnimatedStyle`, as those have to be dynamic.\n\n## Arrays\n\nUsing `filter`, `map` or other array operations in renderers will run the entire operation again for every render.\n\n### Bad\n\n```jsx\nreturn (\n  \u003cText\u003e{users.filter((u) =\u003e u.status === 'online').length} users online\u003c/Text\u003e\n);\n```\n\n### Good\n\n```jsx\nconst onlineCount = useMemo(\n  () =\u003e users.filter((u) =\u003e u.status === 'online').length,\n  [users]\n);\nreturn \u003cText\u003e{onlineCount} users online\u003c/Text\u003e;\n```\n\nYou can also apply this to render multiple React views with `.map`. Those can be memoized with `useMemo` too.\n\n## Functions\n\n### Bad\n\n```jsx\nreturn \u003cView onLayout={(layout) =\u003e console.log(layout)} /\u003e;\n```\n\n### Good\n\n```jsx\nconst onLayout = useCallback((layout) =\u003e {\n  console.log(layout);\n}, []);\nreturn \u003cView onLayout={onLayout} /\u003e;\n```\n\nMake sure to also think about other calls in the renderer, e.g. `useSelector`, `useComponentDidAppear` - wrap the callback there too!\n\n## Forward-propagating Functions\n\n### Bad\n\n```jsx\nfunction MyComponent(props) {\n  return \u003cPressableOpacity onPress={() =\u003e props.logoutUser()} /\u003e;\n}\n```\n\n### Good\n\n```jsx\nfunction MyComponent(props) {\n  return \u003cPressableOpacity onPress={props.logoutUser} /\u003e;\n}\n```\n\n## Objects\n\n### Bad\n\n```jsx\nfunction MyComponent(props) {\n  return (\n    \u003cRecyclerListView scrollViewProps={{ horizontal: props.isHorizontal }} /\u003e\n  );\n}\n```\n\n### Good\n\n```jsx\nfunction MyComponent(props) {\n  const scrollViewProps = useMemo(\n    () =\u003e ({\n      horizontal: props.isHorizontal,\n    }),\n    [props.isHorizontal]\n  );\n  return \u003cRecyclerListView scrollViewProps={scrollViewProps} /\u003e;\n}\n```\n\n## Lift out of render\n\n### Bad\n\n```jsx\nfunction MyComponent() {\n  return \u003cRecyclerListView scrollViewProps={{ horizontal: true }} /\u003e;\n}\n```\n\n### Good\n\n```jsx\nconst SCROLL_VIEW_PROPS = { horizontal: true };\n\nfunction MyComponent() {\n  return \u003cRecyclerListView scrollViewProps={SCROLL_VIEW_PROPS} /\u003e;\n}\n```\n\nThis applies to objects as well as functions which don't depend on the component's state or props. Always use this if you can, since it's even more efficient than `useMemo` and `useCallback`.\n\n## Initial States\n\n### Bad\n\n```jsx\nconst [me, setMe] = useState(users.find((u) =\u003e u.id === myUserId));\n```\n\n### Good\n\n```jsx\nconst [me, setMe] = useState(() =\u003e users.find((u) =\u003e u.id === myUserId));\n```\n\n[The `useState` hook accepts an initializer function](https://reactjs.org/docs/hooks-reference.html#lazy-initial-state). While the first example (\"Bad\") runs the `.find` on every render, the second example only runs the passed function once to initialize the state.\n\n## Count re-renders\n\nWhen writing new components I always put a log statement in my render function to passively watch how often my component re-renders while I'm working on it. In general, components should re-render as little as possible, and if I see a lot of logs appearing in my console I know I did something wrong. It's a good pactice to put this function in your component once you start working on it, and remove it once done.\n\n```jsx\nfunction ComponentImWorkingOn() {\n  // code\n  console.log('re-rendering ComponentImWorkingOn!');\n  return \u003cView /\u003e;\n}\n```\n\nYou can also use the [why-did-you-render](https://github.com/welldone-software/why-did-you-render) library to find out _why_ a component has re-rendered (prop changes, state changes, ...) and possibly catch mistakes early on.\n\n## `React.memo`\n\n### Bad\n\n```jsx\nexport const MyComponent = (props) =\u003e {\n  return ...\n}\n```\n\n### Good\n\n```jsx\nconst MyComponentImpl = (props) =\u003e {\n  return ...\n}\n\nexport const MyComponent = React.memo(MyComponentImpl);\n```\n\nIf your component renders the same result given the same props, you can wrap it in a call to `React.memo(...)` for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result. See [the official docs for `React.memo`](https://reactjs.org/docs/react-api.html#reactmemo), and [use `React.memo(...)` wisely](https://dmitripavlutin.com/use-react-memo-wisely/).\n\n## react-native-performance\n\nIf your app feels slow, try the [react-native-performance](https://github.com/oblador/react-native-performance) library and it's flipper plugin to profile your app's performance in various aspects such as _time to interactive_, _component render time_, _script execution_ and more.\n\n## Disclaimer\n\nDon't prematurely optimize. Some examples used here (e.g. the `useMemo` one) are very small and only demonstrate the idea. A hook like `useMemo also comes with a cost (allocating the function and the deps array, calling the actual hook and running an array comparison), so keep in mind that it is often better to just pass in objects or arrays directly if the component itself is optimized. After a certain component complexity or with a certain dependency graph, memoizing functions can be a huge performance win, but there are also cases where it just leads to unnecessarily complex code and sometimes even worse performance.\nAlways benchmark before and after!\n\n## best-practices hooks and utils\n\n### Installation\n\n```\nnpm i react-native-best-practice\n```\n\n### Usage\n\nAll passing arguments as in native [`React Hooks`](https://reactjs.org/docs/hooks-intro.html)\nlike\n\n```\nimport {useDeepEffect} from 'react-native-best-practice'\n\nuseDeepEffect(()=\u003e{\n\n},[recreatedDeepObject])\n```\n\n#### Hooks list\n\n- `useDeepEffect` =\u003e `useEffect`\n- `useDeepMemo` =\u003e `useMemo`\n- `useDeepCallback` =\u003e `useCallback`\n- `useDeepImperativeHandle` =\u003e `useImperativeHandle`\n- `useDeepLayoutEffect` =\u003e `useLayoutEffect`\n\n### Util\n\n- `isEqual` =\u003e will check isEqual deeply\n- `cloneDeep` =\u003e will clone object and array deeply\n\n# Pro tips\n\n## Monitor RAM, JS framerate, and UI framerate\n\nAlways turn on Pref monitor while developing the app as it will tell you UI framerate and JS framerate, if any frame drops then you can check which new code is causing for dropping frame and making your Time To Interactive (TTI) low, you can open up the `Dev Menu` in your app and toggle `Show Perf Monitor`.\n\u003cimg src=\"/media/pref-monitor.png\" /\u003e\n\n## Use Flashlist for listing\n\nnever use flatlist, always use [flashlist](https://shopify.github.io/flash-list/) as it uses the concept of recycling views, which only create and render a limited number of views that are visible on the screen\n\nhttps://github.com/numandev1/react-native-best-practice/assets/36044436/e20bbe5c-da08-4242-a89c-94a31635ac65\n\n## Custom Logger\n\nCreate a custom Logger instance and enforce emojis to categorize logs. This way it's easier to spot relevant lines in your console, and looks more friendly overall.\nDo lots of logging to save yourself from long nights of debugging at a later point!\n\u003cimg src=\"/media/logger.png\" /\u003e\n\n## Native Stack\n\nAlways use the native-stack from [@reactnavigation](https://github.com/react-navigation/react-navigation)\n. Since it uses platform-native screen primitives, it is almost always worth the performance gains over the JS-based stack.\n\u003cimg src=\"/media/nativestack.jpeg\" /\u003e\n\n## State Management\n\n- **Redux**\n  if you are already using redux then you should use [reselect](https://github.com/reduxjs/reselect) for memoized \"selector\" functions\n\n- **React Context**\n  if you are already using [react context](https://react.dev/reference/react/createContext) then you should use [use-context-selector](https://github.com/dai-shi/use-context-selector) for memoized \"selector\" functions otherwise a context value is changed, all components that useContext will re-render.\n\nrecommended to use these libs [Recoil](https://recoiljs.org/), [Jotai](https://jotai.org/) [Zustand](https://github.com/pmndrs/zustand) for state management\n\n## Ref\n\nif you need to do something in child component from parent component, use [ref](https://react.dev/learn/manipulating-the-dom-with-refs) and [useImperativeHandle](https://react.dev/reference/react/useImperativeHandle) for calling child components functions from parent component instead of playing with state passing into child component\n\n## Buffer\n\nUse the [react-native-buffer](https://github.com/craftzdog/react-native-buffer) fork from [@craftzdog](https://github.com/craftzdog), when dealing with lots of Buffers to speed up your app. It uses C++ backed implementations exposed through JSI, which is roughly 4x faster than the JS-based implementation.\n\u003cimg src=\"/media/buffer.jpeg\" /\u003e\n\n## Storage (MMKV)\n\nUse [react-native-mmkv](https://github.com/mrousavy/react-native-mmkv) to synchronously store and retrieve data from local storage, which persists even on the next app launch.\nCompared to localStorage on Web, MMKV also allows you to encrypt your data and have multiple instances!\n\u003cimg src=\"/media/mmkv.jpeg\" /\u003e\n\n## Image/Video Placeholders\n\nUse [react-native-blurhash](https://github.com/mrousavy/react-native-blurhash) to show beautiful blurry placeholders for your images and videos.\nGenerate a short string that represents a blurry version of your content (\"blurhash\") server-side and send it alongside with your data to the app!\n\u003cimg src=\"/media/blurhash.jpeg\" height=\"450\" /\u003e\n\n## Currencies Handle\n\nWhen presenting numbers to the user, you should format them in the correct locale (commas, currency signs, ..)\nWhile .toLocaleString(..) does it's job, you can actually construct your own NumberFormat instance to improve performance by ~2x!\n\u003cimg src=\"/media/currency-format.jpeg\"  /\u003e\n\n## Safearea insets\n\nAlways handle Safe Area Insets appropriately. Instead of wrapping the entire screen in a \u003cSafeAreaView\u003e, you can work with paddings to create cleaner UIs.\n\nHere, we passed `contentContainerStyle={{ paddingBottom: safeAreaBottom }}` to the \u003cScrollView\u003e:\n\nhttps://github.com/numandev1/react-native-best-practice/assets/36044436/d9e3acef-26a4-43be-b735-e814006532ed\n\n## C++ Book\n\nRead [\"Effective Modern C++\"](/media/Effective_Modern_CPP.pdf).\nEven if you're not a C++ developer, this book will help you understand how memory management works and believe it or not this affects how you think about React (Native).\nIn fact that's the only programming book I ever read\n\nyou'll understand why {} === {} is false, how identity equality works, how re-renders are tons of allocations, how to avoid copies, and lots of other stuff about performance that just makes you think a little bit different when writing code.\nJust don't prematurely optimize 😄\n\nAnd if you want to go into C++ development with JSI, it's even better that you read this book - C++ is not as forgiving as JS.\nIf you make a library that has bad C++ code in it, users will hate you for making their app SIGABRT 😄\n\n## Custom Text Component\n\nNever use the \u003cText\u003e component directly.\nInstead, create your own abstraction so you don't repeat yourself with font name, font size or colors each time and it's easier to change properties at any point.\n\u003cimg src=\"/media/text.png\" /\u003e\nAdditionally, create an ESLint rule to warn you every time you're trying to use \u003cText\u003e instead of \u003cPandaText\u003e ⭐️\n\u003cimg src=\"/media/textEslintRule.png\" /\u003e\n\n## Big Number\n\nWhen dealing with large numbers, use [react-native-bignumber](https://github.com/margelo/react-native-bignumber/) instead of any of the JS-based libraries. ⚡️\nIt is backed by a pure C++ implementation and is ~330x faster than BN.js in certain applications (e.g. #crypto apps, ethers.js, elliptic, bitcoin)\n\u003cimg src=\"/media/bigNumber.png\" /\u003e\n\n## Crypto\n\nWhen working with #crypto / cryptography, use react-native-quick-crypto instead of any of the JS-based libraries. ⚡️\nIt is backed by a pure C++ implementation and is up to 58x faster than [react-native-crypto](https://github.com/margelo/react-native-quick-crypto) or crypto-browserify in certain scenarios.\n\n## Do Measure Performance and Profiling\n\nyou can use [FLASHLIGHT](https://docs.flashlight.dev/) for generateing a performance score for your Android app\n\nyou can do [Profiling](https://www.callstack.com/blog/profiling-react-native-apps-with-ios-and-android-tools) for performance optimization.\n\n## Remove Console.log from production app\n\nYou should remove `console.log` from prod app as using `console.log `statements lowers the FPS, you can remove console.log by reading [this](https://stackoverflow.com/a/69029849/8079868)\n\n# Credits\n\nThanks to [Marc Rousavy](https://github.com/mrousavy) and [\nMargelo](https://github.com/margelo) as mostly best practices are their\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnumandev1%2Freact-native-best-practice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnumandev1%2Freact-native-best-practice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnumandev1%2Freact-native-best-practice/lists"}