官术网_书友最值得收藏!

HOC

The HOC is a pattern that exists to enhance components with additional props or functionality, for instance, if you want to make the component expandable. Instead of just creating a stateful container as we did previously, we could use the HOC pattern. Let's refactor our stateful container component to a HOC and name it makeExpandable:

// src/ Chapter_1/ Example_12_Higher_order_component_makeExpandable/ App.js

const makeExpandable = (ComponentToEnrich) => (

class HelloBoxContainer extends React.Component {
constructor() {
super();
this.state = {
// default state on first render
expanded: false
};
this.expandOrCollapse = this.expandOrCollapse.bind(this);
}

expandOrCollapse() {
// toggle expanded: true becomes false, false becomes true
this.setState({expanded: !this.state.expanded});
}

render = () => (
<ComponentToEnrich
isExpanded={this.state.expanded}
expandOrCollapse={this.expandOrCollapse}
/>
);
}
);

The makeExpandable component accepts ComponentToEnrich. So, we can create a root component (Applike this:

export default makeExpandable(HelloBox);

Cool, isn't it? Now, let's create some other component and enrich it with our HOC. This will be a small button that displays the text hide or show. If the user presses the button, it should show or hide a small colored box. For this task, you can use the following styles:

box: {
width: 100,
height: 100,
backgroundColor: 'powderblue',
}

Place them within StyleSheet.create({ ... }). My solution is pretty straightforward:

// src/ Chapter_1/
// Example_13_Higher_order_component_show_hide_button/ App.js

export const
SomeSection = ({
isExpanded,
expandOrCollapse,
containerStyles,
boxStyle
}) => (
<View style={containerStyles || styles.container}>
<Button
onPress={expandOrCollapse}

title={isExpanded ? "Hide" : "Show"}
color="#841584"
/>
{isExpanded && <View style={boxStyle || styles.box} />}

</View>
);

export default makeExpandable(SomeSection);

In the preceding example, the SomeSection component is wrapped by the makeExpandable HOC, and receives the isExpanded and expandOrCollapse props.

Great! We have just made a reusable HOC, and it is working flawlessly.

Now, I will show you a rather unknown but sometimes useful technique to push your HOC to be even more flexible. Imagine that you are about to enhance a component that is strict about props naming, as in the following example:

export const SomeSection = ({
showHideBox,
isVisible,
containerStyles,
boxStyle
}) => {...};

Unfortunately, our HOC, makeExpandable, is passing the wrong prop names. Let's fix that:

// src/ Chapter_1/ Example_14_Flexible_prop_names_in_HOC/ App.js
render
= () => {
const props = {
[propNames && propNames.isExpanded || 'isExpanded']: this.state.expanded,
[propNames && propNames.expandOrCollapse || 'expandOrCollapse']: this.expandOrCollapse
};
return <ComponentToEnrich {...props} />
};

This is a tricky example. It provides a capability to rename props that are passed down by HOC. To rename it, we need to pass a configuration object called propNames to HOC. If such an object is passed, and it contains a certain key, then we override the name. If the key is not present, then we fall back to the default prop name, for instance, isExpanded.

Notice the use of [] inside of the object. It allows you to dynamically name keys in the object. In this example, the key was dynamically chosen based on the presence of propNames.

To make everything work, we also need to accept the optional argument propNames in the makeExpandable HOC:

const makeExpandable = (ComponentToEnrich, propNames) => (
...
)

Cool! Now our HOC is more flexible when it comes to prop names! We can use it with the aforementioned strict SomeSection component:

export default makeExpandable(SomeSection, {
isExpanded: 'isVisible',
expandOrCollapse:
'showHideBox'
});

Beware of the performance implications when creating variables inside the render function. It will slow your application down. Sometimes, patterns can sacrifice performance a little and sometimes they cannot. Use them wisely. You could also the inline propNames variable as two props.

Make sure to check the next section for a cleaner and decoupled approach.

主站蜘蛛池模板: 曲水县| 朝阳县| 新丰县| 衡东县| 屯留县| 广南县| 边坝县| 鄂州市| 蒙城县| 苏尼特左旗| 苏尼特右旗| 论坛| 衡东县| 库车县| 咸宁市| 健康| 睢宁县| 陆河县| 集贤县| 镇康县| 翼城县| 西峡县| 石棉县| 镇宁| 深泽县| 台南县| 锦州市| 云梦县| 日照市| 常德市| 博兴县| 鱼台县| 灵山县| 吐鲁番市| 长岭县| 桦川县| 乌兰浩特市| 汝阳县| 仙游县| 如皋市| 曲阜市|