HOC vs Render Prop
by Adam Recvlohe
HOC
- Stands for Higher Order Component
- A function that takes a component as an argument and returns a new component
- Great for transforming props and composing functionality
- In the wild: connect (react-redux), withRouter (react-router), withFormik (formik)
- Libraries: recompose
import React, { Component } from "react";
import { render } from "react-dom";
function withHandlers(WrappedComponent) {
return class extends Component {
state = {
name: ""
};
handleChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
render() {
const { handleChange } = this;
const { name } = this.state;
const props = {
name,
handleChange
};
return <WrappedComponent {...this.props} {...props} />;
}
};
}
function Form({ handleChange, name }) {
return <input value={name} name="name" onChange={handleChange} />;
}
const App = withHandlers(Form);
render(<App />, document.getElementById("root"));
Why?
- Separate functionality from presentation
- Testing presentation in isolation
- Develop composable functionality, think pages
- Preference
Render Prop
- A component with a render prop
- Great for dynamic rendering and more terse composition
- In the wild: Motion (react-motion), Transition (react-transition-group), Formik (formik)
import React, { Component } from "react";
import { render } from "react-dom";
class RenderMouseMoves extends Component {
state = {
x: 0,
y: 0
};
handleMouseMove = e => {
this.setState({ x: e.clientX, y: e.clientY });
};
render() {
return (
<div onMouseMove={this.handleMouseMove} style={{ height: "100vh" }}>
{this.props.render(this.state)}
</div>
);
}
}
render(
<RenderMouseMoves
render={({ x, y }) => {
return (
<div>
{x} and {y}
</div>
);
}}
/>,
document.getElementById("root")
);
Why?
- Develop reusable widgets
- Reduce prop overhead/indirection
- Preference
Closing Remarks
Pattern !== Architecture
Questions/Comments
HOC vs Render Prop
By Adam Recvlohe
HOC vs Render Prop
- 1,235