React-beautiful-dnd: React native support?

Created on 26 Jul 2019  路  21Comments  路  Source: atlassian/react-beautiful-dnd

Description

I am using Flat list in react native and I want drag and drop behaviour of cells to move in the mobile application. I am trying the react-beautiful-dnd to replicate that behaviour.
I am getting the following error

TypeError: window.addEventListener is not a function. (In 'window.addEventListener('error', this.onFatalError)', 'window.addEventListener' is undefined)

Here is my code:

import React, {Component} from 'react'
import {SectionList, FlatList, Dimensions, Platform, StyleSheet, Text, View, Button, TextInput, TouchableOpacity, Image, ScrollView} from 'react-native'
import { createStackNavigator, createAppContainer } from "react-navigation"
import SpacesListCell from './SpacesListCell.js'
import {DragDropContext, Droppable} from 'react-beautiful-dnd';


const spaces = [
  {id: '0', spaceName: 'Room'},
  {id: '1', spaceName: 'BathRoom'},
  {id: '2', spaceName: 'Hall'},
  {id: '3', spaceName: 'Kitchen'},
  {id: '4', spaceName: 'Dining'},
  {id: '5', spaceName: 'Living Room'},
  {id: '6', spaceName: 'Study'},
  {id: '7', spaceName: 'Family Room'},
  {id: '8', spaceName: 'TV Room'},
  {id: '9', spaceName: 'Bar'},
  {id: '10', spaceName: 'Library'},
  {id: '11', spaceName: 'Garage'},
  {id: '12', spaceName: 'Balcony'},
  {id: '13', spaceName: 'Verandah'},
  {id: '14', spaceName: 'Garage'},
  {id: '15', spaceName: 'Terrace'},
  {id: '16', spaceName: 'Basement'},
  {id: '17', spaceName: 'Loft'},
  {id: '18', spaceName: 'Passage'},
  {id: '19', spaceName: 'Entrance'},
  {id: '20', spaceName: 'Gym'},
  {id: '21', spaceName: 'StoreRoom'},
  {id: '22', spaceName: 'PrayerRoom'},
  {id: '23', spaceName: 'Outdoors'},
  {id: '24', spaceName: 'Other'},
]

const extractKey = ({ id }) => id

class DemoFile extends Component<Props> {

  constructor () {
    super()
    this.state = {
      spaces: spaces,
    }
  }

  renderCell = ({item}) => {
    return (
      <Droppable droppableId="droppable-1">
        <SpacesListCell title={item.spaceName} index={item.id} id={item.id}/>
      </Droppable>
    )
  }

  renderList = () => {
    return (
        <FlatList
          style={styles.table}
          data={this.state.spaces}
          renderItem={this.renderCell}
          keyExtractor={extractKey}
          legacyImplementation={true}
          extraData={this.state}
        />
    )
  }

  onDragEnd = result => {
    this.setState({
      spaces: result
    })
  }

  render () {
    return (
      <View style={styles.container}>
        <ScrollView contentContainerStyle={styles.containerScrollView}>
        <DragDropContext onDragEnd={this.onDragEnd}>
          <Droppable droppableId='droppableID1'>
          {provided => (
            <FlatList
              style={styles.table}
              data={this.state.spaces}
              renderItem={this.renderCell}
              keyExtractor={extractKey}
              legacyImplementation={true}
              extraData={this.state}
              ref={provided.innerRef}
              {...provided.droppableProps}
            />)}
          </Droppable>
        </DragDropContext>
        </ScrollView>
      </View>
    )
  }
}


const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white'
  },
  table: {
    flex: 1
  },
  containerScrollView: {
    flexGrow: 1,
    justifyContent: 'center',
    alignItems: 'flex-start',
    backgroundColor: '#FFFFFF'
  },
})

module.exports = DemoFile

Here is the code of my cell

import React, {Component} from 'react'
import {Platform, StyleSheet, Text, View, Button, TextInput, TouchableOpacity, Image, ScrollView} from 'react-native'
import {Draggable} from 'react-beautiful-dnd'


class SpacesListCell extends Component<Props> {

  constructor () {
    super()
    this.state = {
      toggle: true
    }
  }


  toggleButton = () => {
    const styles = StyleSheet.create({
      buttonPlusStyles: {
        flex: 0,
        marginLeft: 'auto',
        height: 20,
        width: 20,
        borderRadius: 10,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#7CFC00'
      },
      buttonMinusStyles: {
        flex: 0,
        marginLeft: 'auto',
        height: 20,
        width: 20,
        borderRadius: 10,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#FF3333'
      }
    })

    if (this.state.toggle) {
      return (
        styles.buttonPlusStyles
      )
    } else {
      return (
        styles.buttonMinusStyles
      )
    }
  }

  toggleImage = () => {
    if (this.state.toggle) {
      return (
        <Image source={require('../Assets/plus.png')} style={{height: 15, width: 15}}/>
      )
    } else {
      return (
        <Image source={require('../Assets/minus.png')} style={{height: 15, width: 15}}/>
      )
    }
  }

  cellButtonClicked = () => {

    this.setState({
      toggle: !this.state.toggle
    })
  }

  render () {
    return (
      <Draggable draggableId={this.props.id} index={this.props.index}>
        {(provided) => (
          <TouchableOpacity style={styles.cell}
            {...provided.draggableProps}
            {...provided.dragHandleProps}
          >
            <View style={styles.cellSubContainer}>
              <Image source={require('../Assets/washing-machine.png')} style={{ height: 30, width: 30, marginRight: 30}}/>
              <Text>{this.props.title}</Text>
              <TouchableOpacity style={this.toggleButton()} onPress={() => this.cellButtonClicked()}>
                  {this.toggleImage()}
              </TouchableOpacity>
            </View>
          </TouchableOpacity>
        )}
      </Draggable>
    )
  }

}


const styles = StyleSheet.create({
  cell: {
    flex: 0,
    flexDirection: 'row',
    width: screenWidth,
    height: 60,
    justifyContent: 'flex-start',
    alignItems: 'center',
    borderBottomWidth: 1,
    borderBottomColor: '#CC6666'
  },
  cellSubContainer: {
    flex: 0,
    flexDirection: 'row',
    height: 50,
    width: screenWidth - 60,
    marginLeft: 30,
    justifyContent: 'flex-start',
    alignItems: 'center',
    backgroundColor: 'white'
  }

})


module.exports = SpacesListCell
idea 馃

Most helpful comment

@alexreardon Can we get this library in react native as well ?

All 21 comments

@vedant17 have you found solution for this?

@WahidHasanAriyanto No I haven't been able to find the solution for this

It seems that it is for React JS Browser and not for mobile

@vedant17 well, so what library will you use? i need similar library for my project here

For now I have dropped DnD. If anything I would start by using Pan Handlers.

@WahidHasanAriyanto I was looking around and thought this could help you, https://github.com/computerjazz/react-native-draggable-flatlist Not as polished as react-beautiful-dnd but should be good for your flatlist.

@hbarang thank you so much for spending your time finding this. Actually what i need is a library with capability to drag and drop it's item among the list not only in one list.

React Native support would be huge for our project.

@alexreardon Can we get this library in react native as well ?

Right now the library is super tied to a DOM. It would be a significant undertaking to make it work with react-native

It would be interesting what level of sharing could be achieved between a DOM and native targets

@alexreardon Thanks, would be looking forward to it. :)
React native doesn't have this kind of library yet.

@alexreardon I notice that the Jira app on mobile have dnd. Do you know if they use native app or react-native or other stuff?

I don't know if you are aware of that side of Atlassian though.

Bumping on this one, intrigued to know how Jira's app does it too.

Would love to see this implemented, this is such a beautiful library and would be perfect for the React Native app I'm building.

I too would be interested in this.

I too would be interested in this.

Please +1 on the original issue instead of replying to avoid spamming watchers' inboxes. Thanks!

This would be amazing! Right now I use cross-platform components with react-native and react-native-web. I use a tool called bob that makes publishing for both easy.

I'm gonna try making this work with RNW as a first step, in case anyone is interested. From what I've seen it should be a matter of adapting the styling, especially transition and transform.

@ianmartorell that sounds great, I'm happy to try and help here if we can chart out a path ahead that would make this work with RN mobile too (but agree React Native Web sounds like a good first step). If you could mention any PR/branch here so we can follow your progress that'd be ace.

I've no experience with this library, and it's pretty mature with lots of working parts, so it'd be great if one of the core maintainers would clarify if they're open to PR's on this and maybe help give guidance on the core areas that need to be changed in order for this to work (cc @alexreardon)

I'd love to help too. Please ping me.

react-native-draggable-board might want to take a look at this

Was this page helpful?
0 / 5 - 0 ratings