Reputation: 1636
I'm developing a React Native app. I created my own custom alert
as a component
using modal
. When I use it, I always need to add my alert
component in my render()
function.
Is there any way to use the custom alert without rendering it inside my render()
function?
I mean, I can use Alert
in react-native
by calling it as Alert.alert()
. I want to use my own custom alert also like that.
How can I do that?
Upvotes: 4
Views: 5639
Reputation: 262
You could do this
class SomeComponent extends Component {
static myComponentInstance
constructor(props) {
super(props)
this.state = {
visible: false,
text: ""
}
SomeComponent.myComponentInstance = this
}
static show(text) {
SomeComponent.myComponentInstance._show(text)
}
_show(text) {
this.setState({ visible: true, text })
}
render(){
return (
<Modal visible={this.state.visible}>
<Text>{this.state.text}</Text>
</Modal>
)
}
}
const AppRoot = () => (
<View>
<Navigator />
<SomeComponent/>
</View>
)
And to show it you can do anywhere SomeComponent.show("some text")
Upvotes: 2
Reputation: 2777
As i understood, you want your modal to be handled stateless way. Sadly there is no way to do it without Modal being rendered, buuuut you can do it apart from your app render tree by appending a dummy div and manipulate its dom with render inside your function call.
function modalHandler(CustomModal) {
const div = document.createElement("div");
this.hide = () => {
ReactDOM.unmountComponentAtNode(div);
div.remove();
};
this.show = props => {
document.body.appendChild(div);
ReactDOM.render(<CustomModal onRequestClose={this.hide} {...props} />, div);
};
return {
show: this.show,
hide: this.hide,
};
}
And then create instance for your modal with handler :
const myModal = new modalHandler(CustomModal);
Then you can use your calls anywhere you like without messing your app's render tree:
myModal.show()
myModal.hide()
Example:
const modalStyle = { content: { top: '50%',left: '50%', right: 'auto', bottom: 'auto', marginRight: '-50%', transform: 'translate(-50%, -50%)'}};
const CustomModal = ({ onRequestClose, ...props }) => (
<ReactModal {...props} isOpen={true} contentLabel="CustomModal" >
<h1>This modal will close in 3 seconds</h1>
<button onClick={onRequestClose}>Close</button>
</ReactModal>
);
// Create Stateless Modal handler from component with HOF
function modalHandler(CustomModal) {
const div = document.createElement("div");
this.callOnHide = () => {};
this.callOnShow = () => {};
this.hide = () => {
this.callOnHide();
ReactDOM.unmountComponentAtNode(div);
div.remove();
};
this.show = props => {
this.callOnShow();
document.body.appendChild(div);
ReactDOM.render(<CustomModal onRequestClose={this.hide} {...props} />, div);
};
return {
show: this.show,
hide: this.hide,
setOnHideCallback: callback => {
this.callOnHide = callback;
},
setOnShowCallback: callback => {
this.callOnShow = callback;
}
};
}
// Create instance from modal component
const myModal = new modalHandler(CustomModal);
class View extends React.Component {
openModalHandler = () => {
myModal.show();
// auto close in 3 second
const timer = setTimeout(() => {
myModal.hide();
}, 3000);
// clear the timeout onHide
myModal.setOnHideCallback(()=>{
clearTimeout(timer)
})
};
render() {
return (
<div>
<button onClick={this.openModalHandler}>Open modal</button>
</div>
);
}
}
ReactDOM.render(<View />, document.getElementById("root"));
<script src="https://unpkg.com/[email protected]/dist/react-with-addons.js">
</script>
<script src="https://unpkg.com/[email protected]/dist/react-dom.js">
</script>
<script src="https://unpkg.com/[email protected]/dist/react-modal.min.js">
</script>
<div id="root">
</div>
Upvotes: 0
Reputation: 151
You can also use this API react-native-popup-dialog to design your alert.
Personnaly I did something like that:
...
<Dialog
visible={this.props.visible}>
<DialogContent>
<View style={ container }>
<Text style={ title }> { this.props.title } </Text>
<Text style={ text }> { this.props.text } </Text>
<View style={ buttonView }>
<TouchableOpacity style={ button } onPress={ this.props.validationAction }>
<Text style={ buttonText }>{ this.props.validationText }</Text>
</TouchableOpacity>
</View>
</View>
</DialogContent>
</Dialog>
...
And the parent:
<Alert
visible={ this.state.visible }
title={ "Alert title" }
text={ "This is an custom alert." }
validationText={ "OK" }
validationAction={ () => {
this.setState({ visible: false });
}} />
I hope it will help.
Upvotes: 0
Reputation: 93
Alert.alert()
calls native code.
If you want to display your custom alert component, you'll need to add it to your render method.
It would be easiest to put it in your root or some other parent component.
Set the component to be displayed conditionally. Create a method to set the condition. You can pass this method down to your child components.
this.alertToggle = (displayAlert) => this.setState({displayAlert});
render(){
return (
<Parent>
{this.state.displayAlert && <CustomAlert/>}
<Child alertToggle={this.alertToggle}
</Parent>
)
}
You can call this.props.alertToggle(true)
to display the alert component in the parent.
EDIT: Since you made the component using modal, you could pass the display boolean to the CustomAlert component, and trigger the modal within the component.
<CustomAlert displayAlert={this.state.displayAlert} />
The idea of putting the custom alert in the parent is the same.
Upvotes: 0
Reputation: 16122
Make the method static.
class MyCustomAlert extends React.Component {
static alert () {
}
}
usage
import MyCustomAlert from './MyCustomAlert';
MyCustomAlert.alert()
Upvotes: 0