{"id":20477079,"url":"https://github.com/geoffdavis92/react-floodgate","last_synced_at":"2025-04-13T12:51:33.542Z","repository":{"id":80080454,"uuid":"106470216","full_name":"geoffdavis92/react-floodgate","owner":"geoffdavis92","description":"Configurable and flexible \"load more\" component for React","archived":false,"fork":false,"pushed_at":"2020-10-26T23:58:13.000Z","size":1747,"stargazers_count":29,"open_issues_count":4,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-27T03:51:22.443Z","etag":null,"topics":["es2015","generator-function","javascript","lazy-load","react","ui"],"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/geoffdavis92.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":".github/SUPPORT","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["geoffdavis92"]}},"created_at":"2017-10-10T20:54:29.000Z","updated_at":"2023-08-21T13:14:56.000Z","dependencies_parsed_at":"2023-04-23T06:49:36.902Z","dependency_job_id":null,"html_url":"https://github.com/geoffdavis92/react-floodgate","commit_stats":{"total_commits":247,"total_committers":7,"mean_commits":"35.285714285714285","dds":"0.27125506072874495","last_synced_commit":"d9c434b25f83e31ee3d680441ba22814fd34a92f"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geoffdavis92%2Freact-floodgate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geoffdavis92%2Freact-floodgate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geoffdavis92%2Freact-floodgate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geoffdavis92%2Freact-floodgate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geoffdavis92","download_url":"https://codeload.github.com/geoffdavis92/react-floodgate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248717251,"owners_count":21150388,"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":["es2015","generator-function","javascript","lazy-load","react","ui"],"created_at":"2024-11-15T15:25:26.425Z","updated_at":"2025-04-13T12:51:33.535Z","avatar_url":"https://github.com/geoffdavis92.png","language":"JavaScript","funding_links":["https://github.com/sponsors/geoffdavis92"],"categories":[],"sub_categories":[],"readme":"## Floodgate and it's maintainer [@geoffdavis92](https://github.com/geoffdavis92) stand with the Black community\n\nIf you are financially able, please consider donating to [Black Lives Matter](https://secure.actblue.com/donate/ms_blm_homepage_2019) or any number of metropolitan bail funds ([list in this link](https://bit.ly/bailfundslegalhelp)).\n\nOpen source takes cooperation and expertise from all over the world, from people of all ethnic, racial, and national backgrounds; so does fighting for freedom and against police/state brutality and murder.\n\nBlack. Lives. Matter.\n\n---\n\n\u003ch1 align=\"center\"\u003ereact-floodgate 🌊\u003c/h1\u003e\n\u003cp align=\"center\"\u003eConfigurable and flexible \"load more\" component for React\u003c/p\u003e\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/react-floodgate\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/react-floodgate.svg?style=flat-square\" alt=\"npm version\"\u003e \u003c/a\u003e\n  \u003ca\u003e\u003cimg src=\"https://img.shields.io/github/release/geoffdavis92/react-floodgate.svg?style=flat-square\" alt=\"GitHub release\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/react-floodgate\"\u003e\u003cimg src=\"https://img.shields.io/npm/dt/react-floodgate.svg?style=flat-square\" alt=\"npm downloads\"\u003e \u003c/a\u003e\n  \u003ca href=\"https://github.com/geoffdavis92/react-floodgate/blob/master/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/npm/l/react-floodgate.svg?style=flat-square\" alt=\"npm license\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## The motivation\n\nI have worked on a few client sites and side projects where serialized data is to be displayed concatenated to a given length, with the ability to load more entries after a respective user interaction. \n\nThis can easily result in a complicated mixture of `Array.splice`-ing, potential data mutation, and overly complicated component methods.\n\nSurely there can be a more elegant solution?\n\n## This solution\n\nEnter `react-floodgate`; like its namesake, this component allows for the precise and safe control of resources. Using an [ES2015 generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) as the control mechanism and the [function-as-child](http://mxstbr.blog/2017/02/react-children-deepdive/#function-as-a-child) pattern for flexible and developer-controlled rendering, one can load serialized data into `react-floodgate`, render their desired components, and safely and programmatically iterate through the data as needed.\n\n## The inspiration\n\nThis project was inspired by [Kent Dodd's](https://twitter.com/kentcdodd) [Downshift](https://github.com/paypal/downshift), [this talk](https://www.youtube.com/watch?v=hEGg-3pIHlE) by [Ryan Florence](https://twitter.com/ryanflorence), and [this blog post](http://mxstbr.blog/2017/02/react-children-deepdive/#function-as-a-child) by [Max Stoiber](https://twitter.com/mxstbr).\n\nThis README file modeled after the [Downshift README](https://github.com/paypal/downshift/blob/master/README.md).\n\n## Installation\n\nYou can install the package via [**`npm`**](https://npmjs.org/) or [**`yarn`**](https://yarnpkg.com/):\n\n`$ yarn add react-floodgate`\n\nor\n\n`$ npm i --save react-floodgate`\n\n## Usage\n\nThis is a basic example of Floodgate, showcasing an uncontrolled implementation:\n\n```javascript\nconst BasicExample = props =\u003e (\n  \u003cFloodgate\n    data={[4, 8, 15, 16, 23, 42]}\n    initial={3}\n    increment={1}\n    exportStateOnUnMount={false}\n    onLoadNext={(stateAtLoadNext) =\u003e console.log(stateAtLoadNext)}\n    onLoadAll={(stateAtLoadAll) =\u003e console.log(stateAtLoadAll)}\n    onReset={(stateAtReset) =\u003e console.log(stateAtReset)}\u003e\n    {({ items, loadNext, loadAll, reset, loadComplete }) =\u003e (\n      \u003cdiv\u003e\n        \u003cul\u003e\n          {items.map(number =\u003e \u003cli key={number}\u003e{number}\u003c/li\u003e)}\n        \u003c/ul\u003e\n        \u003cbutton onClick={loadNext} disabled={loadComplete}\u003eLoad More\u003c/button\u003e\n        \u003cbutton onClick={loadAll} disabled={loadComplete}\u003eLoad All\u003c/button\u003e\n        {loadComplete ? \u003cbutton onClick={reset}\u003eReset\u003c/button\u003e : null}\n      \u003c/div\u003e\n    )}\n  \u003c/Floodgate\u003e\n)\n```\n\nUncontrolled Floodgate components are entirely static, and their state will be complete lost/reset when unmounting and re-mounting. In order to ensure internal state is saved during these scenarios, and in order to create dynamic Floodgate components, Floodgate has to be controlled.\n\n### Controlled Floodgate\n\nThe following is a basic example of a controlled Floodgate implementation; this component has a location to save Floodgate state, and uses those values as Floodgate's props. In order to make sure this component does save Floodgate's state, the `onExportState` prop will have to have a function passed to it that saves desired Floodgate state properties to the controlling component's state.\n\n```javascript\nclass FloodgateController extends React.Component {\n  constructor(props) {\n    super();\n    this.state = {\n      showFloodgate: true,\n      FGState: {\n        data: props.data,\n        initial: 3,\n        increment: 3\n      }\n    };\n    this.toggle = this.toggle.bind(this);\n  }\n  toggle() {\n    this.setState(prevState =\u003e ({\n      showFloodgate: !prevState.showFloodgate\n    }));\n  }\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cbutton onClick={this.toggle}\u003eToggle Floodgate\u003c/button\u003e\n        {this.state.showFloodgate ? \u003cFloodgate \n          data={this.state.FGState.data} \n          increment={this.state.FGState.increment} \n          initial={this.state.FGState.initial}\n          exportStateOnUnmount={true}\n          onExportState={newFGState =\u003e this.setState(prevState =\u003e ({\n            FGState: {\n              ...prevState.FGState,\n              ...newFGState,\n              initial: newFGState.currentIndex\n            }\n          }))}\u003e\n          {({ items, loadNext, loadAll, reset, loadComplete }) =\u003e (\n            \u003cdiv\u003e\n              \u003cul\u003e\n                {items.map(number =\u003e \u003cli key={number}\u003e{number}\u003c/li\u003e)}\n              \u003c/ul\u003e\n              \u003cbutton onClick={loadNext} disabled={loadComplete}\u003eLoad More\u003c/button\u003e\n              \u003cbutton onClick={loadAll} disabled={loadComplete}\u003eLoad All\u003c/button\u003e\n              {loadComplete ? \u003cbutton onClick={reset}\u003eReset\u003c/button\u003e : null}\n            \u003c/div\u003e\n          )}\n        \u003c/Floodgate\u003e : null }\n      \u003c/div\u003e\n    );\n  }\n}\n\nconst ControlledFGInstance = \u003cFloodgateController data={[4, 8, 15, 16, 23, 42]} /\u003e;\n```\n\nThis strategy can also be employed to fetch data to pass into Floodgate's `data` prop, or alongside some settings dialogue to allow end-users control over how this feed behaves.\n\n\u003c!-- \n### Floodgate in TypeScript\n\nWhen using TypeScript, Floodgate takes a type parameter that will be applied as the `data` prop's array type; the reasoning for this is so that every element in the `data` prop array is consistent and uniform. \n\nThis helps prevent bugs from being introduced when accessing the `items` property inside the render prop function. \n\nFor example, using the previous example in TypeScript, you would provide the parameter type as `number` (in these examples, the type parameter would be passed down to the `Floodgate` instance from `FloodgateController`):\n\n```typescript\nconst ControlledFGInstance = \u003cFloodgateController\u003cnumber\u003e data={[4, 8, 15, 16, 23, 42]} /\u003e;\n```\n\nThis can take any type you provide, but TypeScript does expect *all* elements in the array to be constrained to that type:\n\n```typescript\ntype AlphaNumeric = number | string;\n\nconst ControlledFGInstance = \u003cFloodgateController\u003cAlphaNumeric\u003e data={[4, 'eight', 15, 'sixteen', 23, 'forty-two']} /\u003e;\n```\n\nElements with mismatched types to the provided type parameter will throw an error:\n\n```typescript\nconst ControlledFGInstance = \u003cFloodgateController\u003c{ first: string, last: string }\u003e data={[{ first: 'Jane', last: 'Doe' }, { first: 'John' }]} /\u003e;\n// [ts] Property 'last' is missing in type '{ first: string; }' but required in type '{ first: string; last: string; }'\n```\n\nIf a component requires the need to accept any type to the `data` prop array, you can pass `any` as the type parameter:\n\n```typescript\nconst ControlledFGInstance = \u003cFloodgateController\u003cany\u003e data={[4, 'eight', 15, 'sixteen', 23, { number: 42 }]} /\u003e;\n```\n\n--\u003e\n\n## API\n\n### `Floodgate` props\n\n| name                   | type        | default      | description                                                                                                 |\n|------------------------|-------------|--------------|-------------------------------------------------------------------------------------------------------------|\n| `data`                 | Array\\\u003cany\u003e | `null`       | The array of items to be processed by `Floodgate`|                                                          |\n| `initial`              | number      | `5`          | How many items are initially available in the render function|                                              |\n| `increment`            | number      | `5`          | How many items are added when calling `loadNext`|                                                           |\n| `exportStateOnUnmount` | boolean     | *(optional)* | Toggle if `exportState` will be called during `componentWillUnmount`                                        |\n| `onExportState`        | Function    | *(optional)* | Function to pass up Floodgate's internal state when `componentWillUnmount` fires or `exportState` is called |\n| `onLoadNext`           | Function    | *(optional)* | Callback function to run after `loadNext`; runs after inline `callback` argument prop                       |\n| `onLoadComplete`       | Function    | *(optional)* | Callback function to run after `loadComplete`; runs after inline `callback` argument prop                   |\n| `onReset`              | Function    | *(optional)* | Callback function to run after `reset`; runs after inline `callback` argument prop                          |\n\n#### `data`\n\n*Type:* `Array\u003cany\u003e = null`\n\nThe array of items to be processed by the `Floodgate` internal queue. \n\nThis array will accept any type of element, but it is recommended to either provide elements with a uniform type, or normalize elements before they get consumed by `Floodgate`. This best practice is to safeguard against the possibility of performing side effects on an element in Floodgate's `render` function that are incompatible with a given element's type; e.g. an element with a type of `{ name: 'Jane Doe', email: 'jane@doe.com' }`, but in the `render` function performing `exampleItem.toUpperCase()`.\n\n\u003c!-- mention TypeScript considerations here, link to #floodgate-in-typescript section --\u003e\n\n#### `initial`\n\n*Type:* `number = 5`\n\nThe length of the first set of items that will be rendered from Floodgate. \u003c!-- If `initial` is negative or zero, this will default to the default value of 5 --\u003e\n\n\u003c!-- TODO: \n  • change \u003e= to \u003e on line 17 of functions.tsx to catch initial values of zero\n  • update loadNext to allow initial values of zero, so allItemsRendered does not get set\n    to true when calling the first zero-length set\n--\u003e\n\n#### `increment`\n\n*Type:* `number = 5`\n\nThe length of subsequent sets of items when calling `loadNext`. \u003c!-- If `increment` is negative or zero, this will default to the default value of 5 --\u003e\n\n#### `exportStateOnUnmount`\n\n*Type:* `boolean = false`\n\nFlag to configure the calling of `props.onExportState` when Floodgate triggers the `componentWillUnmount` component lifecycle event.\n\n#### `onExportState`       \n\n*Arguments:* `{ currentIndex: number, renderedItems: any[], allItemsRendered: boolean }`\n\nProp callback function that executes when Floodgate triggers the `componentWillUnmount` component lifecycle event, or when the [`exportState`](#exportState) is called from the render prop function. It provides a single object argument that represents a set of internal state properties that can be exported to a different component; this is best used on instances that will be toggled (un)mounted, such as in tabs or a single page application.\n\n`currentIndex` is a number representing the index of the last item passed through the queue to `state.renderedItems`.\n\n`renderedItems` is an array of all items that have been passed through the queue from `props.data`.\n\n`allItemsRendered` a boolean describing if all items have been processed by the queue.\n\n#### `onLoadNext`        \n\n*Arguments:* [`Floodgate.state`](https://github.com/geoffdavis92/react-floodgate/blob/8f9ffe83aaae987246d12533671a335032e9f6dd/src/types.d.ts#L33-L43)\n\nCallback property that fires after the `loadNext` method is called. This is executed after `loadNext`'s `callback` method is executed.\n\n#### `onLoadComplete`    \n\n*Arguments:* [`Floodgate.state`](https://github.com/geoffdavis92/react-floodgate/blob/8f9ffe83aaae987246d12533671a335032e9f6dd/src/types.d.ts#L33-L43)\n\nCallback property that fires after the `loadComplete` method is called. This is executed after `loadComplete`'s `callback` method is executed.\n\n#### `onReset`           \n\n*Arguments:* [`Floodgate.state`](https://github.com/geoffdavis92/react-floodgate/blob/8f9ffe83aaae987246d12533671a335032e9f6dd/src/types.d.ts#L33-L43)\n\nCallback property that fires after the `reset` method is called. This is executed after `reset`'s `callback` method is executed.\n\n\n### `render` function\n\n**Note:** the `render` function uses a single object argument to expose the following values/functions. Use the ES2015 destructuring syntax to get the most of this pattern. (see the [Usage](#usage) and [Examples](#examples) sections on how to do this)\n\n| name           | type        | default | parameters                                | description                                                                                                                                                                          |\n|----------------|-------------|---------|-------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `items`        | Array\\\u003cany\u003e | `null`  | n/a                                       | State: the subset of items determined by the `intitial` and `increment` props|                                                                                                       |\n| `loadComplete` | boolean     | `false` | n/a                                       | State: describes if all items have been processed by the `Floodgate` instance|                                                                                                       |\n| `loadAll`      | Function    | n/a     | `{callback?: Function}`                   | Action: loads all `items`; `callback` prop in argument fires immediately after invocation|                                                                                           |\n| `loadNext`     | Function    | n/a     | `{silent?: boolean, callback?: Function}` | Action: loads the next set of items; `callback` prop in argument fires immediately after invocation, `silent` determinse if `onLoadNext` callback is fired after calling `loadNext`| |\n| `reset`        | Function    | n/a     | `{callback?: Function}`                   | Action: resets the state of the `Floodgate` instance to the initial state; `callback` prop in argument fires immediately after invocation|                                           |\n| `exportState`  | Function    | n/a     | `null`                                    | Action: calls the `onExportState` prop callback|                                                                                                                                     |\n#### `items`\n\n*Type:* `Array\u003cany\u003e = null`\n\nSubset of all elements in the `props.data` array, based on the values of the `initial` and `increment` props.\n\nElements of `items` do not have to be rendered at all; for example, `props.data` could be comprised of string manipulation methods, and each member of `items` would then call the respective method on a static value.\n\n#### `loadComplete`\n\n*Type:* `boolean = false`\n\nDescribes if all elements of the `props.data` array have been processed by the internal queue and passed to `items`.\n\n#### `loadAll`\n\n*Arguments:* `{ suppressWarning?: boolean, callback?: Function } = { suppressWarning: false }`\n\nAppends all elements currently in the `data` prop to the `items` array. When called, the `render` argument's `loadComplete` property will be set to `true`, and the `currentIndex` state property will be updated to the length of `Floodgate.props.data`.\n\nThe `supressWarning` argument property determines if a warning should be emitted when all items are rendered`.\n\nThe `callback` argument method will be called after `loadAll` has set the component's state; it will have access to this updated Floodgate `state`.\n\n#### `loadNext`\n\n*Arguments:* `{ silent?: boolean, callback?: Function } = { silent: false }`\n\nAppends the next elements in the `data` prop to the `items` array, length equal to the `increment` prop. When called, will update the `currentIndex` state property; if this increment is equal to or exceeds the length of `data`, the `render` argument's `loadComplete` property will be set to `true`.\n\nThe `silent` argument property determines if this call triggers the `onLoadNext` prop callback.\n\nThe `callback` argument method will be called after `loadNext` has set the component's state; it will have access to this updated Floodgate `state`.\n\n#### `reset`\n\n*Arguments:* `{ initial?: number, callback?: Function } = {}`\n\nResets Floodgate's state to the current instance's `data` and `initial` prop values.\n\nThe `initial` argument property provides the ability to pass in a custom `initial` value to the next rendering after `reset` is called; this is most useful when writing a [controlled Floodgate component](#controlled-floodgate) and the `onExportState` prop is used. For more information on why this is needed, see [pull request #42](https://github.com/geoffdavis92/react-floodgate/pull/42).\n\nThe `callback` argument method will be called after `reset` has set the component's state; it will have access to this updated Floodgate `state`.\n\n#### `exportState`\n\n*Arguments:* `n/a`\n\nCalls the `onExportState` prop callback. Any logic to manipulate and/or save Floodgate's state to a parent component should happen in that prop; since the `onExportState` arguments are not configurable, there are no arguments for `exportState`.\n\n### Using `FloodgateContext`\n\nStarting in `v0.6.0`, Floodgate provides a named export `FloodgateContext` that affords the use of the [React Context API](https://reactjs.org/docs/context.html).\n\nThe `FloodgateContext`'s `Consumer` component exposes the same object argument as the [`Floodgate#render` function](#render-function).\n\n#### Usage\n\nThis `FloodgateContext` object can be used anywhere in the render prop function of a `Floodgate` instance.\n\nFirst, define a component that uses the `Consumer` component:\n```javascript\n// DeepChildControls.js\nimport { FloodgateContext } from \"react-floodgate\";\n\nconst DeepChildControls = (props) =\u003e {\n  return (\n    \u003cdiv\u003e\n      \u003cFloodgateContext.Consumer\u003e\n        {({ loadNext, loadAll, reset }) =\u003e (\n          \u003cReact.Fragment\u003e\n            \u003cbutton onClick={loadNext}\u003eLoad More\u003c/button\u003e\n            \u003cbutton onClick={loadAll}\u003eLoad All\u003c/button\u003e\n            \u003cbutton onClick={reset}\u003eReset\u003c/button\u003e\n          \u003c/React.Fragment\u003e\n        )}\n      \u003c/FloodgateContext.Consumer\u003e\n    \u003c/div\u003e\n  )\n}\n```\n\nThen, import and use this component under a Floodgate render prop:\n```javascript\n// LoadMoreArticles.js\nimport Floodgate from \"react-floodgate\";\nimport DeepChildControls from \"./DeepChildControls\";\n\nexport default function LoadMoreArticles(props) {\n  return (\n    \u003cFloodgate data={props.data} initial={5} increment={5}\u003e\n      {({ items }) =\u003e (\n        \u003cdiv\u003e\n          \u003ch3\u003eArticles\u003c/h3\u003e\n          \u003csection\u003e\n            {items.map((story) =\u003e (\n              \u003carticle\u003e\n                \u003ch4\u003e{story.title}\u003c/h4\u003e\n                \u003cp\u003e{story.excerpt}\u003c/p\u003e\n              \u003c/article\u003e\n            ))}\n            \u003cfooter\u003e\n              {/* Use DeepChildControls here */}\n              \u003cDeepChildControls /\u003e\n            \u003c/footer\u003e\n          \u003c/section\u003e\n        \u003c/div\u003e\n      )}\n    \u003c/Floodgate\u003e\n  )\n}\n```\n\n## Examples\n\n### [Codesandbox Examples](https://codesandbox.io/search?query=\u0026page=1\u0026configure%5BhitsPerPage%5D=12\u0026refinementList%5Btags%5D%5B0%5D=react-floodgate-examples)\n\n- [Floodgate basics](https://codesandbox.io/embed/floodgate-basics-ighcr?fontsize=14\u0026module=%2Fsrc%2Findex.tsx)\n- [Parent-controlled Floodgate](https://codesandbox.io/embed/controlled-floodgate-pp2ww?fontsize=14\u0026module=%2Fsrc%2Findex.tsx)\n- [Floodgate with Context API](https://codesandbox.io/embed/floodgate-context-go1ft?fontsize=14\u0026module=%2Fsrc%2Findex.tsx)\n- [Floodgate with async data polling](https://codesandbox.io/embed/floodgate-polling-app-462lp?fontsize=14\u0026module=%2Fsrc%2Findex.tsx)\n\n### Older Examples:\n\n- [Proof of Concept](https://codesandbox.io/embed/jlzxplj2z9)\n\n## Contributors\n\n### Creating Issues\n\n**[Request a feature](https://github.com/geoffdavis92/react-floodgate/issues/new?template=feature-request.md\u0026projects=geoffdavis92/react-floodgate/1\u0026labels=feature)**\n\n**[Request maintenance](https://github.com/geoffdavis92/react-floodgate/issues/new?template=maintenance.md\u0026projects=geoffdavis92/react-floodgate/1\u0026labels=dx)**\n\n**[Request a documentation update](https://github.com/geoffdavis92/react-floodgate/issues/new?template=documentation.md\u0026projects=geoffdavis92/react-floodgate/3\u0026labels=github,dx)**\n\n### Setup for Development \n\n1. Clone/fork this repository\n2. Install dependencies using yarn or npm.\n3. Run any of the following commands:\n   - `npm run start`: Starts the Rollup watch script for building from `/src`\n   - `npm run storybook`: Starts the [Storybook](https://storybook.js.org/) development environment\n   - `npm run test`: Runs [Jest](https://jestjs.io/) tests once\n   - `npm run test:watch`: Same as `test`, but sets up Jest and watches for changes\n\n## LICENSE\n\n[MIT](blob/master/.github/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeoffdavis92%2Freact-floodgate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeoffdavis92%2Freact-floodgate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeoffdavis92%2Freact-floodgate/lists"}