Originally reported against the @shopify/polaris project on GitHub: https://github.com/Shopify/polaris-react/issues/2009
When using the Modal component from the app bridge react components in an embedded app, if you have multiple modals rendering it will always display the last modal in the component hierarchy even when specifying the open prop for any others.
No matter what Modal has the open prop set to true, the last modal rendered in the entire component hierarchy is the one that is displayed. This is true for components that are deeply nested too. You may change a prop on a Modal in a component based on local state and some other Modal in a disparate part of the component hierarchy will display if it’s rendered later.
The following is a reduced test case that can be put into a create-react-app project with Polaris and app-bridge-react dependencies.
import React, { Component } from 'react';
import {
AppProvider,
Page,
Layout,
Button
} from '@shopify/polaris';
import {
Provider,
Modal
} from '@shopify/app-bridge-react';
const API_KEY = 'CHANGE_ME_1';
const SHOP_ORIGIN = 'CHANGE_ME_2';
export default class App extends Component {
state = {
showModal1: false,
showModal2: false
}
render() {
const { showModal1, showModal2 } = this.state;
const config = {
apiKey: API_KEY,
shopOrigin: SHOP_ORIGIN,
forceRedirect: true
};
return (
<AppProvider>
<Provider config={config}>
<Page>
<Layout sectioned>
<Button onClick={() => this.setState({ showModal1: true })} fullWidth>Display modal</Button>
</Layout>
<Modal
title="Modal 1"
message="Modal 1"
onClose={() => this.setState({ showModal1: false })}
open={showModal1} />
<Modal
title="Modal 2"
message="Modal 2"
onClose={() => this.setState({ showModal2: false })}
open={showModal2} />
</Page>
</Provider>
</AppProvider>
);
}
}
Clicking the Button sets the showModal1 state to true and should display “Modal 1” but “Modal 2” shows up instead. Conditionally rendering the modals does open the correct Modal, but closing them programmatically with the open prop isn’t really possible unless you do it across two separate renders.