bytepool bytepool - 1 month ago 12
iOS Question

Pass function from HOC to component (React, React native)

I am a bloody beginner regarding Facebooks ReactJS and React-native.

So I started coding with help of a tutorial, showing
how to share code between Android and iOS.

Later in this tutorial a button is implemented, which toggles a state.
Unfortunately this is made with a mixin. I want to do it with an HOC-component.

Original mixin

export default {
getInitialState() {
return {
pressed: false
}
},

handlePress() {
this.setState({pressed: !this.state.pressed});
}
}


Original call of above mixin

{ ...
render() {
const buttonStyle = [styles.button];
if (this.state.pressed) buttonStyle.push(styles.buttonPress);
return (
<TouchableOpacity onPress={this.handlePress.bind(this)} style={buttonStyle}>
<Text style={styles.text}>{this.props.text}</Text>
</TouchableOpacity>
)
}
}

reactMixin.onClass(Button, ButtonCommon);
export default Button;


My HOC

export var ButtonComp = (ComposedComponent) => class extends Component {
constructor(props) {
super(props);
this.state = {pressed: false};
}

handlePress() {
this.setState({pressed: !this.state.pressed});
}

render() {
return <ComposedComponent {...this.props} data={this.state.pressed} />;
}
};


My HOC usage

import { ButtonComp } from './button.common';

class Button extends Component {
render() {
const buttonStyle = [styles.button];
if (this.props.data) buttonStyle.push(styles.buttonPress);

return (
<TouchableOpacity onPress={this.handlePress.bind(this)} style={buttonStyle}>
<Text style={styles.text}>{this.props.text}</Text>
</TouchableOpacity>
)
}
}

export default ButtonComp(Button); // Enhanced component


When I execute above code, I get the following error (when the call of this.handle happens, so in the TouchableOpacity tag):

undefined is not an object (evaluating 'this.handlePress.bind')

So what am I doing wrong? Are HOC only to pass data, not functions?
Thanks for the help!

Answer

HOC cannot do that. Yet, in case you want a function from HOC available in the wrapped component to be called there through this, you must pass it through props:

    export var ButtonComp = (ComposedComponent) => class extends Component {
        constructor(props) {
            super(props);
            this.state = {pressed: false};
            this.handlePress = this.handlePress.bind(this);
        }

        handlePress() {
            this.setState({pressed: !this.state.pressed});
        }

        render() {
            return <ComposedComponent {...this.props} handlePress={this.handlePress} data={this.state.pressed} />;
        }
    };

    class Button extends Component {
        render() {
            const buttonStyle = [styles.button];
            if (this.pressed) buttonStyle.push(styles.buttonPress);

            return (
                <TouchableOpacity onPress={this.props.handlePress} style={buttonStyle}>
                    <Text style={styles.text}>{this.props.text}</Text>
                </TouchableOpacity>
            )
        }
    }