@walltowall/map-to-components
v2.0.0
Published
React components to map lists of data to React components
Downloads
5
Keywords
Readme
Map to Components
React component to map a list of data to specified React components. Useful when rendering data from external sources such as block content from a CMS.
Install
npm i @walltowall/map-to-components
Usage
MapToComponents
takes a list of data and renders a list of components using a
provided map. See below for an example:
import { MapToComponents } from "@walltowall/map-to-components"
import { HeroBlock } from "blocks/hero"
import { CallToActionBlock } from "blocks/CallToAction"
// List of blocks that probably comes from a CMS
const list = [
{ id: 1, type: "Hero", text: "Text for a Hero component" },
{ id: 2, type: "CallToAction", text: "Hey", buttonText: "Call Me" },
]
// For each item in the list, get a unique key using `getKey`. `getKey`
// should return a unique value for each item in the list such as an ID
// or UUID. This value will be used as the `key` prop when rendering the
// component.
function getKey(data) {
return data.id
}
// For each item in the list, get a unique type using `getType`. `getType`
// should return a string that corresponds to a React component defined in the
// `map` prop.
function getType(data) {
return data.type
}
// Provide a map whose keys map to React components.
const map = {
Hero: HeroBlock,
CallToAction: (props) => <CallToActionBlock text="Hello World!" {...props} />,
}
const App = () => (
<MapToComponents getKey={getKey} getType={getType} list={list} map={map} />
)
Providing props to components
In the previous example, notice that an item with type CallToAction would render
<CallToActionBlock>
with the prop text="Hello World"
. By creating a new
function component in map, you can provide default props to your components.
This is in contrast to just passing a reference to a component, as is done with
<HeroBlock>
.
By default, no props except key
are passed to components.
To pass props to the components using data derived from the object in the list,
you can provide a mapDataToProps
prop to MapToComponents
.
<MapToComponents
map={{
Hero: HeroBlock,
CallToAction: CallToActionBlock,
}}
mapDataToProps={{
Hero: ({ data }) => ({ text: data.text }),
CallToAction: ({ data }) => ({ buttonText: data.buttonText }),
}}
/>
In the above exmaple, the <HeroBlock>
component receives a text
prop with
the value data.text
, where data
is the element in the list that maps to the
Hero
type.
Each functoin in mapDataToProps
has access to the current element, data about
the element such as index, and data about sibling elements. See the
mapDataToProps
API for reference.
mapDataToContext
There may be times where you need to reference data from other elements in the list, such as the previous or next element, that influences the data you pass to your component.
Using just mapDataToProps
, the only way to access a sibiling's derived data
(i.e. data that is dynamically created, not statically available on the element)
is to set it on mapDataToProp
's return object. Since all values returned from
mapDataToProps
are passed to the element's component, this forces the
contextual data to be passed to the component, which may be unwanted.
Data about the next element is also not available yet as the list is mapped synchronously.
Instead, you can provide a mapDataToContext
prop to create contextual data
about an element. This works exactly like mapDataToProps
. The objects returned
from the mapDataToContext
functions are available to the mapDataToProps
functions under the context
properties.
Unlike mapDataToProps
, data returned from mapDataToContext
is not passed to
the component automatically.
Each function in mapDataToProps
has access to the current element, data about
the element such as index, and data about sibling elements. See the
mapDataToContext
API for reference.
API
MapToComponents
getKey
: (Function) Function that returns a unique key for an element in the list. Required.getType
: (Function) Function that returns the type for an element in the list. Required.list
: (Array): List of data. This can be an array containing mixed types.map
: (Object): Object mapping a data type to a React component to be rendered.mapDataToProps
: (Object) Object mapping a data type to a function returning props for the component to be rendered.mapDataToContext
: (Object) Object mapping a data type to a function returning contextual data for the element.meta
: (Any) Arbitrary data that is made available to functions inmapDataToProps
andmapDataToContext
.default
: (Component) Component to be rendered if an element type is not defined inmap
. This component always receivestype
as a prop.defaultMapDataToProps
: (Function) Function used to determine props for a type not defined inmapDataToProps
.defaultMapDataToContext
: (Function) Function used to determine context for a type not defined inmapDataToContext
.
mapDataToProps
Functions in the object passed to mapDataToProps
and defaultMapDataToProps
are provided an object as their only argument with the following properties:
General
list
: (Array) List of elements.keys
: (Array) List of keys for each element inlist
.types
: (Array) List of types for each element inlist
.comps
: (Array) List of components for each element inlist
.contexts
: (Array) List of context values for each element inlist
.map
: (Object) Mapping of types to React components.meta
: (Any) Data provided to themeta
prop.
Element
data
: (Any) The current element.index
: (Integer) The index for the current element.context
: (Object) The context for the current element.key
: (Any) The key for the current element.type
: (String) The type for the current element.Comp
: (Component) The component for the current element.
Previous element
previousData
: (Any) The previous element.previousContext
: (Object) The context for the previous element.previousKey
: (Any) The key for the previous element.previousType
: (String) The type for the previous element.PreviousComp
: (Component) The component for the previous element.
Next element
nextData
: (Any) The next element.nextContext
: (Object) The context for the next element.nextKey
: (Any) The key for the next element.nextType
: (String) The type for the next element.NextComp
: (Component) The component for the next element.
mapDataToContext
Same signature as mapDataToProps
. All context
properties will be undefined
and should not be used.
Development and Publishing
Tools
- Package manager pnpm, safe and fast
- Release with semantic-release
- Bundle with tsup
- Test with vitest
Publishing
This library uses GitHub Actions to automate publishing when changes are made to
the main
branch. To skip CI (GitHub action), add skip-ci
to a commit
message. To skip release a release, add skip-release
to a commit message.
Ensure that the NPM_TOKEN
secret in the GitHub repository is set with an
appropriate token from npm
.
License
MIT © Wall-to-Wall Studios