npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-native-draglist

v3.8.0

Published

FlatList that reorders items by dragging

Downloads

26,664

Readme

react-native-draglist

npm package Downloads Issues

FlatList that can be reordered by dragging its items

show_me_reordering

Why Does This Exist At All?

Given react-native-draggable-flatlist, why is there also this package?

Great question. react-native-draggable-flatlist has silky-smooth animations, contains dozens of code files, and even manipulates internal data structures in react-native-reanimated to make the animations work. You should absolutely use, and prefer, react-native-draggable-flatlist, if it works for you.

react-native-draglist exists because react-native-reanimated, which react-native-draggable-flatlist depends on, randomly hangs and crashes apps through a variety of issues, several of which have not been fixed despite several major "stable" releases. Furthermore, the hangs and crashes are both frequent and hard to reliably reproduce, making their timely resolution unlikely.

What Is react-native-draglist

This package is a basic version of react-native-draggable-flatlist without dependencies on anything except react and react-native. Specifically, it is deliberately built to avoid react-native-reanimated and its hanging/crashing issues.

It is limited in that it does not animate as smoothly (though it does useNativeDriver). It supports both vertical and horizontal lists.

Installation

With no dependencies outside of react-native and react, this package installs easily:

npm install react-native-draglist

or

yarn add react-native-draglist

Use

All FlatList properties are supported, with the following extensions/modifications:

  • renderItem is now passed a DragListRenderItemInfo, which extends ListRenderItemInfo with these additional fields:

|Field|Type|Note| |--|--|--| |onDragStart|() => void|Your item should call this function when you detect a drag starting (i.e. when the user wants to begin reordering the list). A common implementation is to have a drag handle on your item whose onPressIn calls onDragStart. Alternatively, you could have an onLongPress call this, or use any other mechanism that makes most sense for your UI. DragList will not start rendering items as being dragged until you call this. |onDragEnd|() => void|Your item should call this function when you detect a tap or drag ending. A common implementation is to have a drag handle whose onPressOut calls onDragEnd. If you don't call this during onPressOut, DragList will not not realize your item is no longer active if the user taps but doesn't drag (because you will have called onDragStart, and yet DragList couldn't capture the pan responder from you because the user hasn't moved, thus it doesn't know when the user releases). |isActive|boolean|This is true iff the current item is actively being dragged by the user. This can be used to render the item differently while it's being dragged (e.g. less opacity, different background color, borders, etc).

  • async onReordered(fromIndex: number, toIndex: number) is called once the user drops a dragged item in its new position. This is not called if the user drops the item back in the spot it started. DragList will await this function, and not reset its UI until it completes, so that you can make modifications to the underlying data before the list resets its state.
    • fromIndex will be between 0 and data.length (the total number of items you gave DragList to render).
    • toIndex reflects the position to which the item should be moved in the pre-modified data. It will never equal fromIndex. So, for instance, if toIndex is 0, you should make data[fromIndex] the first element of data. Note: if the user drags the item to the very end of the list, toIndex will equal data.length (i.e. it will reference an index that is one beyond the end of the list).
  • onHoverChanged(index: number) (optional): called whenever an item being dragged changes its index in the list. Note this is only called when the item hasn't been dropped into its final (potentially new) index yet — it's only called as the item hovers around various indices that it could be dropped at.
  • ref: React.RefObject<FlatList<T>> (optional): You can optionally pass a ref, which DragList will tunnel through to the underlying FlatList (via forwardRef). This is useful, for instance, if you want to scrollToIndex yourself on the underlying list.
  • CustomFlatList: typeof FlatList (optional): You can pass any component that implements the same interface as FlatList. Note that the component needs to support all sorts of FlatList things (e.g. ref, scrollToPos, etc) — i.e. it needs to implement the whole FlatList interface, not be just a React.ComponentType<FlatListProps<T>>.

Typical Flow

  1. Set up DragList much like you do any FlatList, except with a renderItem that calls onDragStart at the appropriate time and onDragEnd in onPressOut.
  2. When onReordered gets called, update the ordering of data.

That's basically it.

Show Me The Code

import React, {useState} from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import DragList, {DragListRenderItemInfo} from 'react-native-draglist';

const SOUND_OF_SILENCE = ['hello', 'darkness', 'my', 'old', 'friend'];

export default function DraggableLyrics() {
  const [data, setData] = useState(SOUND_OF_SILENCE);

  function keyExtractor(str: string, _index: int) {
    return str;
  }

  function renderItem(info: DragListRenderItemInfo<string>) {
    const {item, onDragStart, onDragEnd, isActive} = info;

    return (
      <TouchableOpacity
        key={item}
        onPressIn={onDragStart}
        onPressOut={onDragEnd}>
        <Text>{item}</Text>
      </TouchableOpacity>
    );
  }

  async function onReordered(fromIndex: number, toIndex: number) {
    const copy = [...data]; // Don't modify react data in-place
    const removed = copy.splice(fromIndex, 1);

    copy.splice(toIndex, 0, removed[0]); // Now insert at the new pos
    setData(copy);
  }

  return (
    <View>
      <DragList
        data={data}
        keyExtractor={keyExtractor}
        onReordered={onReordered}
        renderItem={renderItem}
      />
    </View>
  );
}

More Discussion

For a great write-up with more details about how to use this library, see this post by Bart den Hollander.

Example Included

To play with the list, you can run the example within example/ in order to test the list yourself by first installing all necessary packages:

npm install
cd example
npm install   # You also need to run this whenever you edit the DragList code.
npm run android   # or `npm run ios`, which takes longer to build

Caveats

This package is implemented with probably 1/10th the files, and 1/20th the advanced concepts, as react-native-draggable-flatlist. The latter even directly modifies unpublished internal data structures of react-native-reanimated, so it's all sorts of advanced in ways that this package will never be. You should prefer, and default to, using react-native-draggable-flatlist unless its random hangs and crashes bother you.

If you have suggestions, or better yet, PRs for how this package can be improved, please connect via GitHub!