marekrozmus / react-swipeable-list

Swipeable list component for React supporting several behaviours (e.g. iOS)
https://marekrozmus.github.io/react-swipeable-list/
MIT License
110 stars 20 forks source link

Wrong counting for React.Children in TrailingActions #54

Open olegkolt opened 11 months ago

olegkolt commented 11 months ago

Describe the bug In some cases Full Swipe with ≤2 children cases an error:

_this.trailingFullSwipeAction is not a function
TypeError: _this.trailingFullSwipeAction is not a function
    at SwipeableListItem.eval [as handleDragEnd] (webpack://react-swipeable-list-example/../src/SwipeableListItem.js?:328:19)
    at eval (webpack://react-swipeable-list-example/../src/SwipeableListItem.js?:174:13)

To Reproduce Create a list of TrailingActions with 'null' as the last child:

<TrailingActions>
  <SwipeAction onClick={handleReject(id)}>
   ...
  </SwipeAction>
  <SwipeAction destructive={true} onClick={handleDelete(id)}>
   ...
  </SwipeAction>
  {null}
</TrailingActions>

Expected behavior No error for cases if some of TrailingActions's children is not valid React element.

Desktop (please complete the following information):

Additional context How to fix: count valid react children before maping:

src/TrailingActions.js:
---
if (Array.isArray(children)) {

    let lastValidChildIndex = 0;

    React.Children.forEach(children, (child, index) => {
        if (React.isValidElement(child)) {
            lastValidChildIndex = index;
        }
    });

    return React.Children.map(children, (child, index) => {
      if (!React.isValidElement(child)) {
        return child;
      }
      return React.cloneElement(child, {
        main: index === lastValidChildIndex,
        trailing: true,
      });
    });
  }
marekrozmus commented 10 months ago

Hi, Thanks for the info. Got a question - why do you want to put something else than SwipeAction inside the TrailingActions? I would like to understand the usecase.

olegkolt commented 10 months ago

Hi, I am mostly about using null inside TrailingActions. There is a problem with a code like:

<TrailingActions>
  {canDelete ? <SwipeAction ...> : null }
  {canArchive ? <SwipeAction ...> : null }
</TrailingActions>

If the last child is null, _this.trailingFullSwipeAction is not a function will appear.