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

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.

主站蜘蛛池模板: 阿拉善左旗| 新邵县| 弥勒县| 玉龙| 称多县| 乡城县| 嘉定区| 类乌齐县| 洪江市| 房山区| 洪江市| 桂平市| 神木县| 密山市| 潢川县| 鲁甸县| 都匀市| 苏尼特左旗| 青州市| 康定县| 通道| 琼结县| 温泉县| 苗栗县| 桃园市| 潮安县| 高青县| 子长县| 鸡东县| 郯城县| 慈利县| 九寨沟县| 凌源市| 临泉县| 烟台市| 左云县| 河曲县| 偏关县| 额敏县| 三穗县| 黄浦区|