user2465134
user2465134

Reputation: 9733

Converting ES5 Mixins to Higher Order Components

In my project I'm trying to get rid of all the mixins and replace them with HOCs. I am stuck using ES5 at the moment.

export default React.createClass({
  mixins: [SomeAsyncMixin],
  data: {
    item1: {
      params: ({params, query}) => {
        params: ({params, query}) => {
          if (!query.p) {
              return null;
          }
          const status = someTernaryResult
          return {
              groups: query.groups,
              status,
              subject: params.subject,
          };
        },
        promise: query => query && query.subject && api(makeUrl(`/some/endpoint`, query))
      },

    item2: {
        params: ({params, query}) => {
          //same as before
        },
        promise: ({subject, query}) => 
          // same as before
    }

    render() {
      // some stuff

      return(
        // some jsx
      );
    }
}

Inside of the mixin, it has a componentWillMount and a componentWillUpdate that runs an update function that will loop through each key on data and update the props/state.

In React's docs about removing mixins, their mixins hold the data, not the component.

There are MANY components in my project that have a data object and use this mixin to update their props/state. How do I make a reusable component to handle this data object?

Also, how do I even access this data object from within the component? In the component this.data is null. Inside of the mixin this.data is the data object from inside the component.. why?

Upvotes: 2

Views: 454

Answers (1)

TLadd
TLadd

Reputation: 6884

Your higher order component and mixin will look very similar. The main difference will be how data, props, and state are shared/passed. In the mixin case, you are altering your component's definition with the mixin's behavior, so the state and props are all in the one resulting component.

In the higher order component case, you are creating a new component that wraps around your other component. Thus, the shared state/behavior is entirely contained within wrapping component, and any data that needs to be used within the wrapped component can be passed via props.

So from what you have in your example, your higher order component would be something like

const someAsync = (data) => (WrappedComponent) => {
    class SomeAsyncComponent extends React.Component {
        constructor(...args) {
            super(...args)

            this.state = {
                ...
            }
        }

        componentWillMount() {
            // Make use of data, props, state, etc
            ...
        }

        componentWillUpdate() {
            ...
        }

        render() {
            // May filter out some props/state, depending on what is needed
            // Can also pass data through if the WrappedComponent needs it.
            return (
                <WrappedComponent
                    { ...this.props }
                    { ...this.state }
                />
            )
        }
    }

    return SomeAsyncComponent 
}

And then your usage of it

export default someAsync(dataConfig)(WrappedComponent)

Upvotes: 1

Related Questions