{"id":14070143,"url":"https://github.com/angeloashmore/react-map-to-components","last_synced_at":"2025-03-19T15:30:22.202Z","repository":{"id":32715037,"uuid":"140211640","full_name":"angeloashmore/react-map-to-components","owner":"angeloashmore","description":"React component to map a list of data to a component based on its type","archived":false,"fork":false,"pushed_at":"2023-01-07T06:58:51.000Z","size":3432,"stargazers_count":9,"open_issues_count":21,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-01T21:02:53.035Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/angeloashmore.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-09T00:08:38.000Z","updated_at":"2024-04-18T18:17:42.000Z","dependencies_parsed_at":"2023-01-14T22:15:24.937Z","dependency_job_id":null,"html_url":"https://github.com/angeloashmore/react-map-to-components","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angeloashmore%2Freact-map-to-components","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angeloashmore%2Freact-map-to-components/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angeloashmore%2Freact-map-to-components/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angeloashmore%2Freact-map-to-components/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/angeloashmore","download_url":"https://codeload.github.com/angeloashmore/react-map-to-components/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243997126,"owners_count":20380981,"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-08-13T07:07:30.418Z","updated_at":"2025-03-19T15:30:21.874Z","avatar_url":"https://github.com/angeloashmore.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# react-map-to-components\n\nReact component to map a list of data to a component based on its type.\n\nThis component is especially useful when processing data from an external source\nwith a flexible nature, such as [Prismic Slices][prismic-slices] and [WordPress\nACF Flexible Content][wordpress-acf-flexible-content].\n\n[![npm version](https://img.shields.io/npm/v/react-map-to-components?style=flat-square)](https://www.npmjs.com/package/react-map-to-components)\n[![Build Status](https://img.shields.io/github/workflow/status/angeloashmore/react-map-to-components/CI?style=flat-square)](https://github.com/angeloashmore/react-map-to-components/actions?query=workflow%3ACI)\n\n```sh\nnpm install --save react-map-to-components\n```\n\n# Usage\n\n`MapToComponents` takes a list and renders a list of components using a mapping\nobject. The following example shows the simplest use case.\n\n```jsx\nimport React from 'react'\nimport MapToComponents from 'react-map-to-components'\n\nconst list = [\n  { id: 1, type: 'HeroBlock', text: 'Text for a Hero component' },\n  { id: 2, type: 'CallToActionBlock', text: 'Hey', buttonText: 'Call Me' },\n  { id: 3, type: 'FooterBlock', year: 2074 },\n]\n\nconst App = () =\u003e (\n  \u003cMapToComponents\n    getKey={(x) =\u003e x.id}\n    getType={(x) =\u003e x.type}\n    list={list}\n    map={{\n      HeroBlock: Hero,\n      CallToActionBlock: CallToAction,\n      FooterBlock: (props) =\u003e \u003cFooter foo=\"bar\" {...props} /\u003e,\n    }}\n  /\u003e\n)\n```\n\nIn this example, `MapToComponents` will render a list of components using `list`\nby performing the following:\n\n1. For each item in the list, get a key using `getKey`. `getKey` should return a\n   unique value for each item in the list, such an an ID or UUID. This value\n   will be used as the `key` prop when rendering the component.\n\n   Read why this is necessary on React's [Lists and Keys][react-keys] guide.\n\n2. For each item in the list, get a type using `getType`. `getType` should\n   return a string with a property in the `map` object corresponding to a React\n   component. If `getType` returns a string without a property in `map`, an\n   error will be thrown by default. **The default behavior can be overriden if\n   you have a default component to render**.\n\n3. Using the key and type for each item in the list, a component is rendered for\n   each item. The component used is determined by the type and component\n   key-value mapping in `map`.\n\nSomething like the following would be rendered by `MapToComponents`:\n\n```jsx\nconst App = [\n  \u003cHero key={1} /\u003e,\n  \u003cCallToAction key={2} /\u003e,\n  \u003cFooter foo=\"bar\" key={3} /\u003e,\n]\n```\n\n## Providing props to components\n\nIn the previous example, notice that an item with type `FooterBlock` would\nrender `\u003cFooter\u003e` with the prop `foo=\"bar\"`. By creating a new function\ncomponent in `map`, you can provide default props to your components. This is in\ncontrast to just passing a reference to a component, as is done with `\u003cHero\u003e`\nand `\u003cCallToAction\u003e`.\n\nBy default, no props **except `key`** are passed to the components.\n\nTo pass props to the components using data derived from the object in the list,\nyou can provide a `mapDataToProps` prop to `MapToComponents`.\n\n### mapDataToProps\n\nTo pass dynamic props to your components, provide an object to the\n`mapDataToProps` prop. This prop is similar to `map` in that your object should\nbe a mapping of a list element's type to a function. The function should return\nan object of props to provide to the type's component.\n\n```jsx\n\u003cMapToComponents\n  getKey={(x) =\u003e x.id}\n  getType={(x) =\u003e x.type}\n  list={list}\n  map={{\n    HeroBlock: Hero,\n    CallToActionBlock: CallToAction,\n    FooterBlock: (props) =\u003e \u003cFooter foo=\"bar\" {...props} /\u003e,\n  }}\n  mapDataToProps={{\n    HeroBlock: ({ data }) =\u003e ({ text: data.text }),\n    CallToAction: ({ data }) =\u003e ({ buttonText: data.buttonText }),\n    FooterBlock: ({ data }) =\u003e ({ year: data.year }),\n  }}\n/\u003e\n```\n\nIn the above example, the `\u003cHero\u003e` component would receive a `text` prop with\nthe value `data.text`, where `data` is the element in the list that maps to the\n`HeroBlock` type.\n\nLikewise, `\u003cCallToAction\u003e` would receive a `buttonText` prop, and `Footer` would\nreceive both `foo` and `year` props.\n\nEach function in `mapDataToProps` has access to the current element, data about\nthe element such as index, and data about sibling elements. See the\n[`mapDataToProps` API](#mapDataToProps2) for a list of all values available.\n\n### mapDataToContext\n\nThere may be times where you need to reference data from other elements in the\nlist, such as the previous or next element, that influences the data you pass to\nyour component.\n\nUsing just `mapDataToProps`, the only way to access a sibiling's derived data\n(i.e. data that is dynamically created, not statically available on the element)\nis to set it on `mapDataToProp`'s return object. Since all values returned from\n`mapDataToProps` are passed to the element's component, this forces the\ncontextual data to be passed to the component, which may be unwanted.\n\nData about the next element is also not available yet as the list is mapped\nsynchronously.\n\nInstead, you can provide a `mapDataToContext` prop to create contextual data\nabout an element. This works exactly like `mapDataToProps`. The objects returned\nfrom the `mapDataToContext` functions are available to the `mapDataToProps`\nfunctions under the `context` properties.\n\nUnlike `mapDataToProps`, data returned from `mapDataToContext` is not passed to\nthe component automatically.\n\nEach function in `mapDataToProps` has access to the current element, data about\nthe element such as index, and data about sibling elements. See the\n[`mapDataToContext` API](#mapDataToContext2) for a list of all values available.\n\n## API\n\n### MapToComponents\n\n- **`getKey`**: (Function) Function that returns a unique key for an element in\n  the list. Required.\n- **`getType`**: (Function) Function that returns the type for an element in the\n  list. Required.\n- **`list`**: (Array): List of data. This can be an array containing mixed\n  types.\n- **`map`**: (Object): Object mapping a data type to a React component to be\n  rendered.\n- **`mapDataToProps`**: (Object) Object mapping a data type to a function\n  returning props for the component to be rendered.\n- **`mapDataToContext`**: (Object) Object mapping a data type to a function\n  returning contextual data for the element.\n- **`meta`**: (Any) Arbitrary data that is made available to functions in\n  `mapDataToProps` and `mapDataToContext`.\n- **`default`**: (Component) Component to be rendered if an element type is not\n  defined in `map`. This component always receives `type` as a prop.\n- **`defaultMapDataToProps`**: (Function) Function used to determine props for a\n  type not defined in `mapDataToProps`.\n- **`defaultMapDataToContext`**: (Function) Function used to determine context\n  for a type not defined in `mapDataToContext`.\n\n### mapDataToProps\n\nFunctions in the object passed to `mapDataToProps` and `defaultMapDataToProps`\nare provided an object as their only argument with the following properties:\n\n#### General\n\n- **`list`**: (Array) List of elements.\n- **`keys`**: (Array) List of keys for each element in `list`.\n- **`types`**: (Array) List of types for each element in `list`.\n- **`comps`**: (Array) List of components for each element in `list`.\n- **`contexts`**: (Array) List of context values for each element in `list`.\n- **`map`**: (Object) Mapping of types to React components.\n- **`meta`**: (Any) Data provided to the `meta` prop.\n\n#### Element\n\n- **`data`**: (Any) The current element.\n- **`index`**: (Integer) The index for the current element.\n- **`context`**: (Object) The context for the current element.\n- **`key`**: (Any) The key for the current element.\n- **`type`**: (String) The type for the current element.\n- **`Comp`**: (Component) The component for the current element.\n\n#### Previous element\n\n- **`previousData`**: (Any) The previous element.\n- **`previousContext`**: (Object) The context for the previous element.\n- **`previousKey`**: (Any) The key for the previous element.\n- **`previousType`**: (String) The type for the previous element.\n- **`PreviousComp`**: (Component) The component for the previous element.\n\n#### Next element\n\n- **`nextData`**: (Any) The next element.\n- **`nextContext`**: (Object) The context for the next element.\n- **`nextKey`**: (Any) The key for the next element.\n- **`nextType`**: (String) The type for the next element.\n- **`NextComp`**: (Component) The component for the next element.\n\n### mapDataToContext\n\nSame signature as [`mapDataToProps`](#mapDataToProps#2). All `context`\nproperties will be `undefined` and should not be used.\n\n[prismic-slices]: https://prismic.io/feature/dynamic-layout-content-components\n[wordpress-acf-flexible-content]:\n  https://www.advancedcustomfields.com/resources/flexible-content/\n[react-keys]: https://reactjs.org/docs/lists-and-keys.html#keys\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fangeloashmore%2Freact-map-to-components","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fangeloashmore%2Freact-map-to-components","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fangeloashmore%2Freact-map-to-components/lists"}