carbon icon indicating copy to clipboard operation
carbon copied to clipboard

fix(16916): adds React fragment support for Switcher's direct child

Open 2nikhiltom opened this issue 1 year ago • 5 comments

Closes https://github.com/carbon-design-system/carbon/issues/16916

This PR fix an issue where the Switcher component crashes when a React Fragment is used as a direct child. It's fix involves modifying the child handling logic to properly handle the Fragment case

Changelog

New

  • Added flattening logic for children, including those within Fragments
  • Introduced unique index and key generation for Fragment children
if (child.type === React.Fragment) {
          // Handle React.Fragment case
          return React.Children.toArray(child.props.children).map(
            (fragmentChild, fragmentIndex) =>
              React.isValidElement(fragmentChild)
                ? React.cloneElement(fragmentChild as React.ReactElement<any>, {
                    handleSwitcherItemFocus,
                    index: `${index}-${fragmentIndex}`,
                    key: `${index}-${fragmentIndex}`,
                    expanded,
                  })
                : fragmentChild
          );
        } 

Changed

  • Updated childrenWithProps to use flatMap instead of map
  • Modified handleSwitcherItemFocus to work with flattened children
const flattenedChildren = React.Children.toArray(children).flatMap(
     (child) =>
       React.isValidElement(child) && child.type === React.Fragment
         ? React.Children.toArray(child.props.children)
         : child
   );

Testing / Reviewing

  1. Verify that when Switcher component is passed with React Fragments as direct children, application does not crash
  2. Verify focus navigation | keyboard navigation works like before
  3. Verify that the existing functionality is intact

Note : Need to remove the fragments added for testing purpose before merging

2nikhiltom avatar Jul 22 '24 09:07 2nikhiltom

Deploy Preview for v11-carbon-react ready!

Built without sensitive environment variables

Name Link
Latest commit 957ba1f1abd5d7eb26c3a6e8cf3f00b712959bb7
Latest deploy log https://app.netlify.com/sites/v11-carbon-react/deploys/66e31c308d4a6e00088e039e
Deploy Preview https://deploy-preview-17008--v11-carbon-react.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

netlify[bot] avatar Jul 22 '24 09:07 netlify[bot]

Deploy Preview for carbon-elements ready!

Name Link
Latest commit 957ba1f1abd5d7eb26c3a6e8cf3f00b712959bb7
Latest deploy log https://app.netlify.com/sites/carbon-elements/deploys/66e31c30e36e9500084892c3
Deploy Preview https://deploy-preview-17008--carbon-elements.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

netlify[bot] avatar Jul 22 '24 09:07 netlify[bot]

Did you look at https://github.com/grrowl/react-keyed-flatten-children? It only has a single dependency on react-is. We could use it in our components, but it also looks like consumers can use it on their own to use fragments if they'd like. It's referred to on the react thread regarding Children.toArray not traversing fragments. Thoughts?

tay1orjones avatar Jul 26 '24 16:07 tay1orjones

Hey @tay1orjones , react-keyed-flatten-children makes sure that it flatten arrays and React.Fragments into a regular, one-dimensional array while ensuring element and fragment keys are preserved, unique, and stable between renders.

The current implementation works fairly fine for single level of nesting, preserving keys and props placed on nested and non-nested children and fragments becomes messy incase of multilevel nesting which is exactly solved by above utility.

The currently purpose of Switcher is to provides a way for the user to easily navigate between products and systems and expects a SwitcherItem as its direct child as SwitcherItem is expected to have a link/href to redirect somewhere when clicked Instead of modifying the Switcher component to accommodate this, it makes more sense for consumers to use the react-keyed-flatten-children package to manage their use cases. This will keeps dependencies light and the component source clean.

2nikhiltom avatar Aug 05 '24 07:08 2nikhiltom

Instead of modifying the Switcher component to accommodate this, it makes more sense for consumers to use the react-keyed-flatten-children package to manage their use cases. This will keeps dependencies light and the component source clean.

@2nikhiltom Nice, I see this outlined in the package docs. This makes the most sense to me. So instead of making these changes to Switcher, could this PR be updated to document using react-keyed-flatten-children? Maybe in a new document named /packages/react/docs/composition.md?

tay1orjones avatar Aug 12 '24 14:08 tay1orjones

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 76.82%. Comparing base (fdb31d9) to head (957ba1f).

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #17008   +/-   ##
=======================================
  Coverage   76.82%   76.82%           
=======================================
  Files         408      408           
  Lines       13973    13973           
  Branches     4341     4337    -4     
=======================================
  Hits        10735    10735           
  Misses       3064     3064           
  Partials      174      174           

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

codecov[bot] avatar Sep 12 '24 07:09 codecov[bot]