{"id":19149798,"url":"https://github.com/harness/ff-react-native-client-sdk","last_synced_at":"2025-05-07T04:44:48.307Z","repository":{"id":37798209,"uuid":"355257949","full_name":"harness/ff-react-native-client-sdk","owner":"harness","description":null,"archived":false,"fork":false,"pushed_at":"2025-02-12T21:53:08.000Z","size":2347,"stargazers_count":3,"open_issues_count":3,"forks_count":7,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-07T04:44:41.412Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/harness.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-06T16:28:41.000Z","updated_at":"2025-02-12T21:52:49.000Z","dependencies_parsed_at":"2024-05-01T20:42:47.761Z","dependency_job_id":"9050677d-a4bf-446b-b2b3-6d1b07757a58","html_url":"https://github.com/harness/ff-react-native-client-sdk","commit_stats":{"total_commits":59,"total_committers":16,"mean_commits":3.6875,"dds":0.728813559322034,"last_synced_commit":"ef684a7f591ef07d63634060a32f1ae8b9c11676"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harness%2Fff-react-native-client-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harness%2Fff-react-native-client-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harness%2Fff-react-native-client-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harness%2Fff-react-native-client-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/harness","download_url":"https://codeload.github.com/harness/ff-react-native-client-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252816520,"owners_count":21808702,"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":[],"created_at":"2024-11-09T08:09:36.872Z","updated_at":"2025-05-07T04:44:48.287Z","avatar_url":"https://github.com/harness.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Native Client SDK For Harness Feature Flags\n\n[![React version][react-badge]][reactjs]\n[![React Native version][react-native-badge]][reactnative]\n[![TypeScript version][ts-badge]][typescript-4-7]\n[![Node.js version][nodejs-badge]][nodejs]\n[![APLv2][license-badge]][license]\n\nUse this README to get started with our Feature Flags (FF) Client SDK for React Native. This guide outlines the basics\nof getting started with the SDK and provides a full code sample for you to try out.\n\nThis sample doesn't include configuration options, for in depth steps and configuring the SDK, see\nthe [React Native Client SDK Reference](https://developer.harness.io/docs/feature-flags/ff-sdks/client-sdks/react-native-client).\n\n## Requirements\n\nTo use this SDK, make sure you’ve:\n\n- Installed Node.js v16 or a newer version\n- Installed React.js v17 or a newer version\n\nTo follow along with our test code sample, make sure you’ve:\n\n- [Created a Feature Flag on the Harness Platform](https://developer.harness.io/docs/feature-flags/ff-creating-flag/create-a-feature-flag/)\n  called `harnessappdemodarkmode`\n- [Created a client SDK key](https://developer.harness.io/docs/feature-flags/ff-creating-flag/create-a-project#create-an-sdk-key)\n  and made a copy of it\n- Created a project using [Expo](https://expo.dev/tools#cli)\n\n```shell\nnpx create-expo-app my-demo-app\ncd my-demo-app\nnpm install\n```\n\n## Installing the SDK\n\nThe first step is to install the FF SDK as a dependency in your application. To install using npm, use:\n\n```shell\nnpm install @harnessio/ff-react-native-client-sdk\n```\n\nOr to install with yarn, use:\n\n```shell\nyarn add @harnessio/ff-react-native-client-sdk\n```\n\n## Code Sample\n\nThe following is a complete code example using Expo that you can use to test the `harnessappdemodarkmode` flag you\ncreated on the Harness Platform. When you run the code it will:\n\n- Render a loading screen\n- Connect to the FF service\n- Retrieve all flags\n- Access a flag using the `useFeatureFlag` hook\n- Access several flags using the `useFeatureFlags` hook\n\nThe following code can be placed in the `src/App.js` file.\n\n```typescript jsx\nimport { StyleSheet, Text, View } from 'react-native'\nimport { StatusBar } from 'expo-status-bar'\n\nimport {\n  FFContextProvider,\n  useFeatureFlag,\n  useFeatureFlags\n} from '@harnessio/ff-react-native-client-sdk'\n\nexport default function App() {\n  return (\n    \u003cView style={styles.container}\u003e\n      \u003cFFContextProvider\n        apiKey=\"YOUR_API_KEY\"\n        target={{\n          identifier: 'YOUR_TARGET_IDENTIFIER', // \u003c- replace with an identifier unique to the user, e.g. email or UUID\n          name: 'YOUR TARGET NAME' // \u003c- replace with a name unique to the user\n        }}\n      \u003e\n        \u003cSingleFeatureFlag /\u003e\n        \u003cMultipleFeatureFlags /\u003e\n      \u003c/FFContextProvider\u003e\n\n      \u003cStatusBar style=\"auto\" /\u003e\n    \u003c/View\u003e\n  )\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    backgroundColor: 'orange',\n    alignItems: 'center',\n    justifyContent: 'center',\n    minHeight: '100%'\n  }\n})\n\nfunction SingleFeatureFlag() {\n  const flagValue = useFeatureFlag('harnessappdemodarkmode')\n\n  return (\n    \u003cText\u003eThe value of \"harnessappdemodarkmode\" is {JSON.stringify(flagValue)}\u003c/Text\u003e\n  )\n}\n\nfunction MultipleFeatureFlags() {\n  const flags = useFeatureFlags()\n\n  return (\n    \u003c\u003e\n      \u003cText\u003eHere are all our flags:\u003c/Text\u003e\n      \u003cText\u003e{JSON.stringify(flags, null, 2)}\u003c/Text\u003e\n    \u003c/\u003e\n  )\n}\n```\n\n## Async mode\n\nBy default, the React Native Client SDK will block rendering of children until the initial load of feature flags has\ncompleted. This ensures that children have immediate access to all flags when they are rendered. However, in some\ncircumstances it may be beneficial to immediately render the application and handle display of loading on a\ncomponent-by-component basis. The React Native Client SDK's asynchronous mode allows this by passing the\noptional `asyncMode` prop when connecting with the `FFContextProvider`.\n\n## Streaming and polling\n\nBy default, the React Native Client SDK will set up a stream to keep the feature flag values up-to-date when things\nchange in your Harness project. When a change is made in the Harness project, Harness will send an event to the SDK and\nthe SDK will serve the changed value. This is great when your application needs to change in near-real-time when a\nfeature flag changes (for example, your application might need to display a maintenance screen when the backend APIs are\nbeing updated). However, in some circumstances, polling might be a better option. When streaming is disabled and polling\nis enabled, the SDK will periodically poll for current feature flag values and keep your application up-to-date. By\ndefault, the interval for polling is 60 seconds and can be adjusted to suit your application.\n\n### Streaming\n\nStreaming is enabled by default and can be disabled using the `streamEnabled` option and passing `false`. In the event\nthat the stream is interrupted, the SDK will attempt to reconnect automatically. If after a number of attempts the\nstream cannot be re-established, the SDK will switch to polling unless specifically disabled using the `pollingEnabled`\noption.\n\n### Polling\n\nPolling is disabled by default and can be enabled using the `pollingEnabled` option and passing `true`. When enabled,\nthe SDK will poll for feature flag value changes every 60 seconds, this can be adjusted using the `pollingInterval`\noption and passing the number of milliseconds you want the SDK to wait between polling.\n\n## Caching evaluations\n\nIn practice flags rarely change and so it can be useful to cache the last received evaluations from the server to allow\nyour application to get started as fast as possible. Setting the `cache` option as `true` or as an object (see interface\nbelow) will allow the SDK to store its evaluations to `localStorage` and retrieve at startup. This lets the SDK get\nstarted near instantly and begin serving flags, while it carries on authenticating and fetching up-to-date evaluations\nfrom the server behind the scenes.\n\n```typescript jsx\n\u003cFFContextProvider\n  apiKey=\"YOUR_API_KEY\"\n  target={{\n    identifier: 'YOUR_TARGET_IDENTIFIER',\n    name: 'YOUR TARGET NAME'\n  }}\n  options={{\n    cache: true\n  }}\n\u003e\n  \u003cMyApp /\u003e\n\u003c/FFContextProvider\u003e\n```\n\nThe `cache` option can also be passed as an object with the following options.\n\n```typescript\ninterface CacheOptions {\n  // maximum age of stored cache, in ms, before it is considered stale\n  ttl?: number\n  // storage mechanism to use, conforming to the Web Storage API standard, can be either synchronous or asynchronous\n  // defaults to localStorage\n  storage?: AsyncStorage | SyncStorage\n  // use target attributes when deriving the cache key\n  // when set to `false` or omitted, the key will be formed using only the target identifier and SDK key\n  // when set to `true`, all target attributes with be used in addition to the target identifier and SDK key\n  // can be set to an array of target attributes to use a subset in addition to the target identifier and SDK key\n  // defaults to false\n  deriveKeyFromTargetAttributes?: boolean | string[]\n}\n\ninterface SyncStorage {\n  getItem: (key: string) =\u003e string | null\n  setItem: (key: string, value: string) =\u003e void\n  removeItem: (key: string) =\u003e void\n}\n\ninterface AsyncStorage {\n  getItem: (key: string) =\u003e Promise\u003cstring | null\u003e\n  setItem: (key: string, value: string) =\u003e Promise\u003cvoid\u003e\n  removeItem: (key: string) =\u003e Promise\u003cvoid\u003e\n}\n```\n\n## Overriding the internal logger\n\nBy default, the React Client SDK will log errors and debug messages using the `console` object. In some cases, it\ncan be useful to instead log to a service or silently fail without logging errors.\n\n```typescript jsx\nconst myLogger = {\n  debug: (...data) =\u003e {\n    // do something with the logged debug message\n  },\n  info: (...data) =\u003e {\n    // do something with the logged info message\n  },\n  error: (...data) =\u003e {\n    // do something with the logged error message\n  },\n  warn: (...data) =\u003e {\n    // do something with the logged warning message\n  }\n}\n\nreturn (\n  \u003cFFContextProvider\n    apiKey=\"YOUR_API_KEY\"\n    target={{\n      identifier: 'YOUR_TARGET_IDENTIFIER',\n      name: 'YOUR TARGET NAME'\n    }}\n    options={{\n      logger: myLogger\n    }}\n  \u003e\n    \u003cMyApp /\u003e\n  \u003c/FFContextProvider\u003e\n)\n```\n\n## Fast startup\n\nBy default, the React Native Client SDK will connect to the Harness Feature Flags service to get the current feature\nflag values and then render your application. Using a combination of the `cache` option\n(see [Caching evaluations](#caching-evaluations) above) and Async mode (see [Async mode](#async-mode) above), you can\ninstruct the SDK to instead render immediately using previously cached values (in the case of a returning user) or\ndefault values (in the case of new users). The SDK will immediately render your application and asynchronously connect\nto the Harness Feature Flags service to make sure the cached feature flag values are kept up-to-date.\n\n```typescript jsx\n\u003cFFContextProvider\n  asyncMode\n  apiKey=\"YOUR_API_KEY\"\n  target={{\n    identifier: 'YOUR_TARGET_IDENTIFIER',\n    name: 'YOUR TARGET NAME'\n  }}\n  options={{\n    cache: true\n  }}\n\u003e\n  \u003cMyApp /\u003e\n\u003c/FFContextProvider\u003e\n```\n\n## API\n\n### `FFContextProvider`\n\nThe `FFContextProvider` component is used to set up the React context to allow your application to access feature flags\nusing the `useFeatureFlag` and `useFeatureFlags` hooks\nand `withFeatureFlags` [HOC](https://reactjs.org/docs/higher-order-components.html). At minimum, it requires\nthe `apiKey` you have set up in your Harness Feature Flags account, and the `target`. You can think of a `target` as a\nuser.\n\nThe `FFContextProvider` component also accepts an `options` object, a `fallback` component, an array\nof `initialEvaluations`, an `onError` handler, and can be placed in [Async mode](#Async-mode) using the `asyncMode`\nprop.\nThe `fallback` component will be displayed while the SDK is connecting and fetching your flags. The `initialEvaluations`\nprop allows you pass an array of evaluations to use immediately as the SDK is authenticating and fetching flags.\nThe `onError` prop allows you to pass an event handler which will be called whenever a network error occurs.\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport { FFContextProvider } from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent() {\n  return (\n    \u003cFFContextProvider\n      asyncMode={false} // OPTIONAL: whether or not to use async mode\n      apiKey=\"YOUR_API_KEY\" // your SDK API key\n      target={{\n        identifier: 'YOUR_TARGET_IDENTIFIER', // replace with a unique ID for the Target \n        name: 'YOUR TARGET NAME',  // replace with the unique name of the Target\n        attributes: { // OPTIONAL: key/value pairs of attributes of the Target\n          customAttribute: 'this is a custom attribute',\n          anotherCustomAttribute: 'this is something else'\n        }\n      }}\n      fallback={\u003cText\u003eLoading...\u003c/Text\u003e} // OPTIONAL: component to display when the SDK is connecting\n      options={{ // OPTIONAL: advanced configuration options\n        cache: false,\n        baseUrl: 'https://url-to-access-flags.com',\n        eventUrl: 'https://url-for-events.com',\n        streamEnabled: true,\n        debug: false,\n        eventsSyncInterval: 60000,\n        pollingEnabled: false,\n        pollingInterval: 60000\n      }}\n      initialEvaluations={evals} // OPTIONAL: array of evaluations to use while fetching\n      onError={handler} // OPTIONAL: event handler to be called on network error\n    \u003e\n      \u003cCompontToDisplayAfterLoad /\u003e \u003c!-- component to display when Flags are available --\u003e\n    \u003c/FFContextProvider\u003e\n  )\n}\n```\n\n### `useFeatureFlag`\n\nThe `useFeatureFlag` hook returns a single named flag value. An optional second argument allows you to set what value\nwill be returned if the flag does not have a value. By default `useFeatureFlag` will return `undefined` if the flag\ncannot be found.\n\n\u003e N.B. when rendered in [Async mode](#Async-mode), the default value will be returned until the flags are retrieved.\n\u003e Consider using the [useFeatureFlagsLoading hook](#usefeatureflagsloading) to determine when the SDK has finished\n\u003e loading.\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport { useFeatureFlag } from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent() {\n  const myFlagValue = useFeatureFlag('flagIdentifier', 'default value')\n\n  return \u003cText\u003eMy flag value is: {myFlagValue}\u003c/Text\u003e\n}\n```\n\n### `useFeatureFlags`\n\nThe `useFeatureFlags` hook returns an object of flag identifier/flag value pairs. You can pass an array of flag\nidentifiers or an object of flag identifier/default value pairs. If an array is used and a flag cannot be found, the\nreturned value for the flag will be `undefined`. If no arguments are passed, all flags will be returned.\n\n\u003e N.B. when rendered in [Async mode](#Async-mode), the default value will be returned until the flags are retrieved.\n\u003e Consider using the [useFeatureFlagsLoading hook](#usefeatureflagsloading) to determine when the SDK has finished\n\u003e loading.\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport { useFeatureFlag } from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent() {\n  const myFlagValues = useFeatureFlags()\n\n  return (\n    \u003c\u003e\n      \u003cText\u003eMy flag values are:\u003c/Text\u003e\n      \u003cText\u003e{JSON.stringify(myFlagValues, null, 2)}\u003c/Text\u003e\n    \u003c/\u003e\n  )\n}\n```\n\n#### Get a subset of Flags\n\n```typescript jsx\nconst myFlagValues = useFeatureFlags(['flag1', 'flag2'])\n```\n\n#### Get a subset of Flags with custom default values\n\n```typescript jsx\nconst myFlagValues = useFeatureFlags({\n  flag1: 'defaultForFlag1',\n  flag2: 'defaultForFlag2'\n})\n```\n\n### `useFeatureFlagsLoading`\n\nThe `useFeatureFlagsLoading` hook returns a boolean value indicating whether the SDK is currently loading flags from the\nserver.\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport {\n  useFeatureFlagsLoading,\n  useFeatureFlags\n} from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent() {\n  const isLoading = useFeatureFlagsLoading()\n  const flags = useFeatureFlags()\n\n  if (isLoading) {\n    return \u003cText\u003eLoading...\u003c/Text\u003e\n  }\n\n  return (\n    \u003c\u003e\n      \u003cText\u003eMy flag values are:\u003c/Text\u003e\n      \u003cText\u003e{JSON.stringify(flags, null, 2)}\u003c/Text\u003e\n    \u003c/\u003e\n  )\n}\n```\n\n### `useFeatureFlagsClient`\n\nThe React Native Client SDK internally uses the Javascript Client SDK to communicate with Harness. Sometimes it can be\nuseful to be able to access the instance of the Javascript Client SDK rather than use the existing hooks or higher-order\ncomponents (HOCs). The `useFeatureFlagsClient` hook returns the current Javascript Client SDK instance that the React\nNative Client SDK is using. This instance will be configured, initialized and have been hooked up to the various events\nthe Javascript Client SDK provides.\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport {\n  useFeatureFlagsClient,\n  useFeatureFlagsLoading\n} from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent() {\n  const client = useFeatureFlagsClient()\n  const loading = useFeatureFlagsLoading()\n\n  if (loading || !client) {\n    return \u003cText\u003eLoading...\u003c/Text\u003e\n  }\n\n  return (\n    \u003cText\u003e\n      My flag value is: {client.variation('flagIdentifier', 'default value')}\n    \u003c/Text\u003e\n  )\n}\n```\n\n### `ifFeatureFlag`\n\nThe `ifFeatureFlag` higher-order component (HOC) wraps your component and conditionally renders only when the named flag\nis enabled or matches a specific value.\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport { ifFeatureFlag } from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent() {\n  return \u003cText\u003eThis should render if the flag is on\u003c/Text\u003e\n}\n\nconst MyConditionalComponent = ifFeatureFlag('flag1')(MyComponent)\n```\n\nYou can then use `MyConditionalComponent` as a normal component, and only render if `flag1`'s value is truthy.\n\n#### Conditionally with a specific value\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport { ifFeatureFlag } from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent() {\n  return \u003cText\u003eThis should render if the flag evaluates to 'ABC123'\u003c/Text\u003e\n}\n\nconst MyConditionalComponent = ifFeatureFlag('flag1', { matchValue: 'ABC123' })(\n  MyComponent\n)\n```\n\nYou can then use `MyConditionalComponent` as a normal component, and only render if `flag1`'s value matches the passed\ncondition.\n\n#### Loading fallback when in async mode\n\nIf [Async mode](#Async-mode) is used, by default the component will wait for flags to be retrieved before showing. This\nbehaviour can be overridden by passing an element as `loadingFallback`; when loading the `loadingFallback` will be\ndisplayed until the flags are retrieved, at which point the component will either show or hide as normal.\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport { ifFeatureFlag } from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent() {\n  return \u003cText\u003eThis should render if the flag is on\u003c/Text\u003e\n}\n\nconst MyConditionalComponent = ifFeatureFlag('flag1', {\n  loadingFallback: \u003cText\u003eLoading...\u003c/Text\u003e\n})(MyComponent)\n```\n\n### `withFeatureFlags`\n\nThe `withFeatureFlags` higher-order component (HOC) wraps your component and adds `flags` and `loading` as additional\nprops. `flags` contains the evaluations for all known flags and `loading` indicates whether the SDK is actively fetching\nflags.\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport { withFeatureFlags } from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent({ flags }) {\n  return \u003cText\u003eFlag1's value is {flags.flag1}\u003c/Text\u003e\n}\n\nconst MyComponentWithFlags = withFeatureFlags(MyComponent)\n```\n\n#### Loading in async mode\n\nIf [Async mode](#Async-mode) is used, the `loading` prop will indicate whether the SDK has completed loading the flags.\nWhen loading completes, the `loading` prop will be `false` and the `flags` prop will contain all known flags.\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport { withFeatureFlags } from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent({ flags, loading }) {\n  if (loading) {\n    return \u003cText\u003eLoading...\u003c/Text\u003e\n  }\n\n  return \u003cText\u003eFlag1's value is {flags.flag1}\u003c/Text\u003e\n}\n\nconst MyComponentWithFlags = withFeatureFlags(MyComponent)\n```\n\n### `withFeatureFlagsClient`\n\nThe React Native Client SDK internally uses the Javascript Client SDK to communicate with Harness. Sometimes it can be\nuseful to be able to access the instance of the Javascript Client SDK rather than use the existing hooks or higher-order\ncomponents (HOCs). The `withFeatureFlagsClient` HOC wraps your component and adds `featureFlagsClient` as additional\nprop. `featureFlagsClient` is the current Javascript Client SDK instance that the React Native Client SDK is using. This\ninstance will be configured, initialized and have been hooked up to the various events the Javascript Client SDK\nprovides.\n\n```typescript jsx\nimport { Text } from 'react-native'\nimport { withFeatureFlagsClient } from '@harnessio/ff-react-native-client-sdk'\n\n// ...\n\nfunction MyComponent({ featureFlagsClient }) {\n  if (featureFlagsClient) {\n    return (\n      \u003cText\u003e\n        Flag1's value is {featureFlagsClient.variation('flag1', 'no value')}\n      \u003c/Text\u003e\n    )\n  }\n\n  return \u003cText\u003eThe Feature Flags client is not currently available\u003c/Text\u003e\n}\n\nconst MyComponentWithClient = withFeatureFlagsClient(MyComponent)\n```\n\n## Additional Reading\n\nFor further examples and config options, see\nthe [React Native Client SDK Reference](https://developer.harness.io/docs/feature-flags/ff-sdks/client-sdks/react-native-sdk-reference/)\nFor more information about Feature Flags, see\nour [Feature Flags documentation](https://developer.harness.io/docs/feature-flags/ff-onboarding/getting-started-with-feature-flags/).\n\n[ts-badge]: https://img.shields.io/badge/TypeScript-4.7-blue.svg\n\n[react-badge]: https://img.shields.io/badge/React.js-\u003e=%2016.7-blue.svg\n\n[react-native-badge]: https://img.shields.io/badge/React%20Native-\u003e=%200.70.0-blue.svg\n\n[nodejs-badge]: https://img.shields.io/badge/Node.js-\u003e=%2012-blue.svg\n\n[nodejs]: https://nodejs.org/dist/latest/docs/api/\n\n[reactjs]: https://reactjs.org\n\n[reactnative]: https://reactnative.dev\n\n[typescript-4-7]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html\n\n[license-badge]: https://img.shields.io/badge/license-APLv2-blue.svg\n\n[license]: https://github.com/drone/ff-nodejs-server-sdk/blob/main/LICENSE\n\n[jest]: https://facebook.github.io/jest/\n\n[eslint]: https://github.com/eslint/eslint\n\n[prettier]: https://prettier.io\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharness%2Fff-react-native-client-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fharness%2Fff-react-native-client-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharness%2Fff-react-native-client-sdk/lists"}