0

When I look at the following line in this example:

const SortableItem = SortableElement(({value}) => <li>{value}</li>);

then I don't understand where is the lambda function ({value}) => <li>{value}</li> used in SortableElement ?

Can someone please enlighten me ?

SortableElement's code:

import React, {Component, PropTypes} from 'react';
import {findDOMNode} from 'react-dom';
import invariant from 'invariant';

// Export Higher Order Sortable Element Component
export default function SortableElement (WrappedComponent, config = {withRef: false}) {
    return class extends Component {
        static displayName = (WrappedComponent.displayName) ? `SortableElement(${WrappedComponent.displayName})` : 'SortableElement';
        static WrappedComponent = WrappedComponent;
        static contextTypes = {
            manager: PropTypes.object.isRequired
        };
        static propTypes = {
            index: PropTypes.number.isRequired,
            collection: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
            disabled: PropTypes.bool
        };
        static defaultProps = {
            collection: 0
        };
        componentDidMount() {

            let {collection, disabled, index} = this.props;

            if (!disabled) {
                this.setDraggable(collection, index);
            }
        }
        componentWillReceiveProps(nextProps) {
            const {index} = this.props;
            if (index !== nextProps.index && this.node) {
                this.node.sortableInfo.index = nextProps.index;
            }
            if (this.props.disabled !== nextProps.disabled)
            {
                let {collection, disabled, index} = nextProps;
                if (disabled) {
                    this.removeDraggable(collection);
                }
                else {
                    this.setDraggable(collection, index);
                }
            }
        }
        componentWillUnmount() {
            let {collection, disabled} = this.props;

            if (!disabled) this.removeDraggable(collection);
        }
        setDraggable(collection, index){
            let node = this.node = findDOMNode(this);

            node.sortableInfo = {index, collection};

            this.ref = {node};
            this.context.manager.add(collection, this.ref);
        }
        removeDraggable(collection) {
            this.context.manager.remove(collection, this.ref);
        }
        getWrappedInstance() {
            invariant(config.withRef, 'To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableElement() call');
            return this.refs.wrappedInstance;
        }
        render() {
            const ref = (config.withRef) ? 'wrappedInstance' : null;
            return (
                <WrappedComponent ref={ref} {...this.props} />
            );
        }
    }
}
jhegedus
  • 20,244
  • 16
  • 99
  • 167

3 Answers3

1

Thanks to ({value}) => <li>{value}</li> in
const SortableItem = SortableElement(({value}) => <li>{value}</li>);
we will be actually rendering an li element with a value passed as a prop from the map method below.

const SortableList = SortableContainer(({items}) => {
    return (
        <ul>
            {items.map((value, index) =>
                <SortableItem key={`item-${index}`} index={index} value={value} />
            )}
        </ul>
    );
});

In the context of the SortableElement's API code the important thing is that it renders the WrappedComponent (lines 67-69). We can treat SortableElement as any other Higher Order Component - a component that wraps another component to deliver some extra functionality. In this case - a fancy sorting animation of the lambda function.

Piotr Berebecki
  • 7,428
  • 4
  • 33
  • 42
1
export default function SortableElement (WrappedComponent, config = {withRef: false}) {
  return class extends Component {

    ...

    render() {
      const ref = (config.withRef) ? 'wrappedInstance' : null;
      return (
        <WrappedComponent ref={ref} {...this.props} />
      );
    }
  }
}

Look at the render() method in the returned React Component by the higher order SortableElement function, the lambda function (which is a stateless component) is passed as the first argument to the higher order function, and this first argument is going to end up as being the parameter WrappedComponent you see in the signature of this higher order function.

So this higher order function is going to spit a React component with a render() method that uses/calls your actual React component that you just passed in (the lambda function).

<WrappedComponent ref={ref} {...this.props} />
Diego Zacarias
  • 793
  • 2
  • 12
  • 22
1

Put simply ({value}) => <li>{value}</li> is a short hand for

React.crateClass({
    render:function(){
        return <li>{this.props.value}</li> 
    }
})

refer to pure functional component in React

and SortableElement is a higher order component wrapping another React component ,such the functional component above

Guichi
  • 2,150
  • 1
  • 19
  • 27
  • note that `({value}) =>
  • {value}
  • ` desugars to `(props) => { var value = props.value; return
  • {value}
  • }` as I was kindly told at #reactjs – jhegedus Oct 06 '16 at 14:57