1

In the following JSFiddle, I am trying to create a Sortable list using jQuery UI in React.js, so that I can recreate a bug that I am getting in production with proprietary code I'm working on.

Since I can't easily use the Node.js event emitter in JSFiddle, I tried to use jQuery's trigger and on instead. That isn't working below, so I can't recreate the error.

Here is a link to the JSFiddle: http://jsfiddle.net/bengrunfeld/zoyeejxr/

If I can get the following code working, then I can move forward in recreating the real error I'm having.

EDIT: I've tried just attaching trigger and on to document, but it breaks the jQuery-UI Sortable plugin for some reason.

Le code:

_list = {
    fruit: [
    'apple',
    'banana',
    'cherry',
    'date'
    ]
};

var Entry = React.createClass({
    render:function(){
        return (
           <div className="entry">{this.props.content}</div> 
        )
    }
});

var Shop = React.createClass({
    render:function(){
        var data = this.props.data.fruit;

        var fruitOrder = data.map(function(node, i) {
            return (
                <Entry key={i} content={node}>{node}</Entry>
            );
        });

        return (
            <div className="shop">{fruitOrder}</div>
        )
    }
});

function getList() {
  return { data: _list }
}

var Basket = React.createClass({
    getInitialState: function(){
        return getList();
    },
    componentWillMount: function(){
        $('.basket').on('sort', function(data){
            // Show that this works
            console.log('this works');

            // Swap item position in the array to recreate React
            // swapping error
            var tmp = _list.fruit[0];
            _list.fruit[0] = _list.fruit[1];
            _list.fruit[1] = tmp;
            this.setState(getList());
        });
    },
    sortIndexes: function(data) {
        console.log(data);
    },
    buttonClicked: function(e){
    },
    render: function() {
        return (
            <div className="basket">
                <p>Drag and drop the fruits</p>
                <Shop data={this.state.data} />
            </div>
            )
    }
});

React.render(
    <Basket />, 
    document.body
    );


  $('.shop').sortable({
    axis: "y",
    containment: "parent",
    tolerance: "pointer",
    revert: 150,
    start: function (event, ui) {
      ui.item.indexAtStart = ui.item.index();
    },
    stop: function (event, ui) {
      var data = {
        indexStart: ui.item.indexAtStart,
        indexStop: ui.item.index(),
      };
      $('.basket').trigger('sort');
    },
  });
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Ben
  • 5,085
  • 9
  • 39
  • 58

1 Answers1

2

As Olim Saidov pointed in his comment, DOM is not yet rendered when componentWillMount is called. You should move event binding to componentDidMount.

Another issue in your code is that you need to bind this in callback to jQuery's on.

Try to replace your componentWillMount with this code:

componentDidMount: function(){
    var _this = this;
    $('.basket').on('sort', function(data){
        console.log('this works');
        var tmp = _list.fruit[0];
        _list.fruit[0] = _list.fruit[1];
        _list.fruit[1] = tmp;
        _this.setState(getList());
    });
},

http://jsfiddle.net/zoyeejxr/16/

max taldykin
  • 12,459
  • 5
  • 45
  • 64
  • So the real issue that I'm dealing with is listed here: [http://stackoverflow.com/questions/29725136/jquery-ui-sortable-with-react-js-buggy](http://stackoverflow.com/questions/29725136/jquery-ui-sortable-with-react-js-buggy). If you'd be able to help me out with this, I'd greatly appreciate it. – Ben Apr 19 '15 at 06:50