@walltowall/react-map-slices-to-components
TypeScript icon, indicating that this package has built-in type declarations

0.4.1 • Public • Published

react-map-slices-to-components

Extends react-map-to-components to suit rendering a list of Prismic Slices. It adds the following features:

  • Sensible defaults for getKey and getTypes.
  • Override a component mapping by passing a map of curried functions to the mapOverrides prop.
  • Modify the list of slices using a function passed to the listMiddleware prop.
  • Renders a neutral default slice when a mapping is missing. Limited to the development environment.

Install

npm install --save react-map-slices-to-components react-map-to-components

Note that react-map-to-components is a peer dependency.

Usage

Default props

Defaults for getKey and getType props are configured to work with Prismic.

  • getKey: Returns the id or key field of the slice with priority given to id.
  • getType: Returns the __typename field of the slice.

You can easily override them by passing the appropriate prop.

// To override defaults:
<MapSlicesToComponents
  getKey={/* custom logic to get key */}
  getType={/* custom logic to get type */}
  {...props}
/>

Change styling for a specific slice

If you need to change styling for a specific slice, you can utilize the mapOverrides prop. This prop allows you to replace the default mapping for any slice type. When overriding a slice, you receive the original slice component if you simply want to pass new props to it. If you want to replace the component completly, the original slice can be ignored.

In the following example, we change the background of a PageBodyImageBlurb slice to red only if it follows a PageBodyHeroImage slice. Note that <Comp> here is the same as <PageBodyImageBlurb>.

<MapSlicesToComponents
  map={/* your slice map */}
  mapOverrides={{
    PageBodyImageBlurb: Comp => props => {
      const overrideProps = {}

      if (props.previousType === 'PageBodyHeroImage') overrideProps.bg = 'red'

      return <Comp {...props} {...overrideProps} />
    },
  }}
/>

Notice how we continue to spread props on the slice in addition to overrideProps. This ensures the slice continues to receive all the props it would have normally received. Since overrideProps is spread after props, any props declared before it will be replaced if present in overrideProps.

Change data for a specific slice

As shown above, you have access to the slice's props. For example, the PageBodyImageBlurb slice from our previous example may take in a heading prop. If you wanted to manipulate that data before it gets to PageBodyImageBlurb, you could override its value.

<MapSlicesToComponents
  map={/* your slice map */}
  mapOverrides={{
    PageBodyImageBlurb: Comp => ({ heading, ...props }) => {
      // mockingcase returns a mOcKiNgCaSe version of its input
      const newHeading = mockingcase(heading)

      return <Comp {...props} heading={newHeading} />
    },
  }}
/>

We can manipulate any of its props using arbitrary JavaScript. Note that we spread props on the returned component to ensure the slice continues to receive all the props it expects.

Change the list of slices

mapOverrides allows you to alter the returned component for a slice, but it does not allow you to determine the order in which it is rendered. MapSlicesToComponents takes a listMiddleware prop that provides functionality to do just that.

listMiddleware accepts a function that accepts a list of slices as its only input and returns a modified version of that list. Modifications could include whitelisting or blacklisting slice types, reordering slices, or injecting slices that do not exist anywhere else.

// Removes slices with the GraphQL typename `PrismicPageBodyHeroImage`.
const noPageBodyHeroImage = filter(
  slice => slice.__typename !== 'PrismicPageBodyHeroImage',
)

// Flips the order of the slices using Lodash's reverse function.
const reverseSlices = _.reverse

// Adds a SecretSlice to the list as the third element. Since the object is
// passed directly to the slice, you can include any data, including functions.
const addSecretSlice = list => {
  const secretSliceData = {
    __typename: 'SecretSlice',
    id: 'uniqueId',
    data: {
      handleButtonClick: () => console.log('Functions in data!'),
    },
  }

  list.splice(2, 0, secretSliceData)

  return list
}

// Using the listMiddleware prop.
const Page = () => (
  <MapSlicesToComponents
    list={/* your list */}
    listMiddleware={/* middleware function here */}
  />
)

listMiddleware affects the raw list of slices before it is processed through mapDataToProps and map. listMiddleware is a low-level API that allows you to manipulate the data before MapToComponents processes it.

Providing Global Enhancers

It may be desireable to define global behavior for your mapped props or context objects. In these cases, you can provide the mapDataToPropsEnhancer and mapDataToContextEnhancer as props to MapSlicesToComponents. You can think of an enhancer as a middleware that runs after your original mapping function.

An enhancer receives the props or context object from the return value of a slice's mapDataToProps or mapDataToContext slice as it's first argument, and the rest of the data you would normally have in mapDataToProps or mapDataToContext as the second argument.

An enhancer must return the final shape of props or context for that slice. See below for an example.

// Define your global enhancer.
const mapDataToPropsEnhancer = (props, { previousType }) => {
  return {
    isPreviousHeader: previousType === 'Header'
    // Spreading props here allows the original props in the slice
    // to have priority over enhancer props.
    ...props,
  }
}

// Use the enhancer.
const Page = () => (
  <MapSlicesToComponents
    mapDataToPropsEnhancer={mapDataToPropsEnhancer}
  />
)

Readme

Keywords

Package Sidebar

Install

npm i @walltowall/react-map-slices-to-components

Weekly Downloads

1

Version

0.4.1

License

MIT

Unpacked Size

42.3 kB

Total Files

12

Last publish

Collaborators

  • kalamak
  • walltowall-dev
  • angeloashmore
  • asyarb
  • kangken