Martin Mazza Dawson Martin Mazza Dawson - 17 days ago 5
Javascript Question

React Higher Order Component Initial Props

I am creating a player library and want the React flow to go like this:

PlayerHOC -> PlaylistHOC -> FooterContainer
.

The reason I want it to go in this direction is that
PlayerHOC
has methods on it that
PlaylistHOC
and
FooterContainer
need to access (i.e from props).

My code:

class FooterContainer extends React.Component {
render() {
return (
<div>
<div className="jp-type-footer" >
//...
</div>
</div>
);
}
}

class FooterPlayer extends React.Component {
constructor() {
super();

this.options = {
smoothPlayBar: false,
muted: true,
//...
};
}
render() {
return (
<Player {...this.options} />
);
}
};

export const PlaylistHOC = (WrappedComponent) => class extends React.Component {
constructor(props) {
super(props);

//Add a new stateClass for the extra loop option
this.stateClass = merge({
shuffled: "state-shuffled",
loopedPlaylist: "state-loop-playlist"
}, this.props.stateClass);
}
setPlaylist = () => {}
};

export const PlayerHOC = (WrappedComponent) => class extends React.Component {
constructor(props) {
super(props);

//get passed in props from FooterPlayer and PlaylistHoc
}
play = () => {}
pause = () => {}
};

const Player = PlayerHOC(PlaylistHOC(FooterContainer));

export default connect()(FooterPlayer);


I also pass in props from
FooterPlayer
to
PlayerHOC
which works fine. However, I also want to pass in default props from
PlaylistHOC
to
PlayerHOC
that will never be updated and I can't figure out how to this while also keeping this flow.

For example:
const Player = PlaylistHOC(PlayerHOC(FooterContainer));
this would allow me to pass in initial props from
PlaylistHOC
and
FooterPlayer
to
PlayerHOC
but then I would not be able to access
PlayerHOC
methods by props.

How do I do this?

Answer

I would use const Player = PlaylistHOC(PlayerHOC(FooterContainer)); because a parent component can't receive props from it's children.

Looks like both PlaylistHOC and PlayerHOC are mixins, so they should inherit from the component being wrapped instead of React.Component.

I've changed a code just a little bit to be able to test it, but the key idea of it is how I've extended WrappedComponent instead of React.Component in your mixins.

class FooterContainer extends React.Component {
    render() {
        return (
            <div>
                <div className="jp-type-footer">
                    <button onClick={this.play.bind(this)}>Play</button>
                </div>
            </div>
        );
    }
}

class FooterPlayer extends React.Component {
    constructor() {
        super();

        this.options = {
            smoothPlayBar: false,
            muted: true
            //...
        };
    }
    render() {
        return (
            <Player {...this.options} />
        );
    }
};

export const PlaylistHOC = (WrappedComponent) => class extends WrappedComponent {
    constructor(props) {
        super(props);

        //Add a new stateClass for the extra loop option
        //this.stateClass = merge({
        //      shuffled: "state-shuffled",
        //    loopedPlaylist: "state-loop-playlist"
        //}, this.props.stateClass);
    }
    setPlaylist() {

    }
};

export const PlayerHOC = (WrappedComponent) => class extends WrappedComponent {
    constructor(props) {
        super(props);

        //get passed in props from FooterPlayer and PlaylistHoc
    }
    play() {
      console.log('playing');
    }
    pause() {

    }
};

const Player = PlaylistHOC(PlayerHOC(FooterContainer));

export default connect()(FooterPlayer);

By the way, try decorators for some really fancy syntax like

@PlayerlistHOC
@PlayerHOC
class FooterContainer {

}

Be warned decorators are not definitive and might change a lot.

Comments