Creating component with some pattern.

Creating component with some pattern.
One of the common riddles is writing custom view with pattern, such as group of modals each having own title and content. You could write separate component to create every modal. But it's very inelegant, so you can create simply something like this:
<Modal isVisible={this.props.isVisible} onBackdropPress={this.props.action}>
 <View style={styles.modalContainer}>
   <View>
     <Text style={styles.titleModal}>{this.props.title}</Text>
   </View>
   {this.props.children}
 </View>
</Modal>

and bam! You've created component with custom pattern! Everything seems easy so far, but now is the moment where it gets interesting. How to mount each content to modal without creating complex switch or some other mess? Well, you could simply create object which has every content inside itself:

const modalData = {
 logOut: LogOutModal,
 myLocation: myLocationModal
}

and... this is where we meet some issue. You can adress object by passing some variable in square brackets, like: modalData[this.state.content], but there is no way to do it in JSX tag! It's not possible to pass variable like: <modalData[this.state.content]/>, of course you can do it like: <modalData.logOut/>, but it also means you would have to use a complex switch. So how we can solve this problem? React docs helps us with JSX in Depth article (https://reactjs.org/docs/jsx-in-depth.html), where we can find solution:

import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
 photo: PhotoStory,
 video: VideoStory
};

function Story(props) {
 // Correct! JSX type can be a capitalized variable.
 const SpecificStory = components[props.storyType];
 
 return <SpecificStory story={props.story} />;
}

and that's what we need to do! So in our case it would be like:

modalContent = () => {
 const ModalContent = modalDataBase[this.state.content];
return <ModalContent />;
}

and the only thing left is to insert it:

<InfoModal isVisible={this.state.isVisible} title={this.state.title} action={() => this.hideModal()} >
 {this.modalContent()}
</InfoModal>

And we're done!

Post a comment