L'approche que je suggère, c'est un peu verbeux, mais je l'ai trouvé à l'échelle assez bien à des applications complexes. Lorsque vous souhaitez afficher un modal, le feu d'une action décrivant ce qui modale vous voulez voir:
En envoyant une Action pour Montrer la Modale
this.props.dispatch({
type: 'SHOW_MODAL',
modalType: 'DELETE_POST',
modalProps: {
postId: 42
}
})
(Chaînes de caractères peuvent être des constantes, bien sûr; je suis à la volée des chaînes pour des raisons de simplicité.)
L'écriture d'un Réducteur pour Gérer l'État Modal
Ensuite, assurez-vous d'avoir un réducteur juste accepte ces valeurs:
const initialState = {
modalType: null,
modalProps: {}
}
function modal(state = initialState, action) {
switch (action.type) {
case 'SHOW_MODAL':
return {
modalType: action.modalType,
modalProps: action.modalProps
}
case 'HIDE_MODAL':
return initialState
default:
return state
}
}
/* .... */
const rootReducer = combineReducers({
modal,
/* other reducers */
})
Super! Maintenant, lorsque vous envoi une action, state.modal
sera mis à jour pour inclure les informations sur le actuellement visible fenêtre modale.
L'écriture de la Racine de la Composante Modale
À la racine de votre hiérarchie des composants, ajouter un <ModalRoot>
composant qui est connecté à la Redux magasin. Il sera à l'écoute de state.modal
et affichage approprié modal composant, de transférer les accessoires de l' state.modal.modalProps
.
// These are regular React components we will write soon
import DeletePostModal from './DeletePostModal'
import ConfirmLogoutModal from './ConfirmLogoutModal'
const MODAL_COMPONENTS = {
'DELETE_POST': DeletePostModal,
'CONFIRM_LOGOUT': ConfirmLogoutModal,
/* other modals */
}
const ModalRoot = ({ modalType, modalProps }) => {
if (!modalType) {
return <span /> // after React v15 you can return null here
}
const SpecificModal = MODAL_COMPONENTS[modalType]
return <SpecificModal {...modalProps} />
}
export default connect(
state => state.modal
)(ModalRoot)
Qu'avons-nous fait ici? ModalRoot
indique le courant modalType
et modalProps
de state.modal
auquel il est connecté, et rend un composant correspondant comme DeletePostModal
ou ConfirmLogoutModal
. Chaque modal est un composant!
L'Écriture Spécifique Modale Des Composants
Il n'existe pas de règles générales ici. Ils sont simplement Réagir face à des composants de l'expédition d'actions, de lire quelque chose à partir du magasin de l'etat, et juste arriver à être les auxiliaires modaux.
Par exemple, DeletePostModal
pourrait ressembler à:
import { deletePost, hideModal } from '../actions'
const DeletePostModal = ({ post, dispatch }) => (
<div>
<p>Delete post {post.name}?</p>
<button onClick={() => {
dispatch(deletePost(post.id)).then(() => {
dispatch(hideModal())
})
}}>
Yes
</button>
<button onClick={() => dispatch(hideModal())}>
Nope
</button>
</div>
)
export default connect(
(state, ownProps) => ({
post: state.postsById[ownProps.postId]
})
)(DeletePostModal)
L' DeletePostModal
est connecté à la boutique il possible d'afficher le titre du post et fonctionne comme n'importe quel composant connecté: il peut envoyer des actions, y compris l' hideModal
lorsqu'il est nécessaire de se cacher.
L'extraction d'une Présentation de la Composante
Il serait maladroit de copier-coller la même logique de présentation pour chaque "spécifique" modal. Mais vous avez des composants, droit? De sorte que vous pouvez extraire une présentation <Modal>
composant qui ne sait pas ce qu'particulier les auxiliaires modaux faire, mais les poignées de la façon dont ils regardent.
Ensuite, spécifiques des modaux tels que DeletePostModal
pouvez l'utiliser pour le rendu:
import { deletePost, hideModal } from '../actions'
import Modal from './Modal'
const DeletePostModal = ({ post, dispatch }) => (
<Modal
dangerText={`Delete post ${post.name}?`}
onDangerClick={() =>
dispatch(deletePost(post.id)).then(() => {
dispatch(hideModal())
})
})
/>
)
export default connect(
(state, ownProps) => ({
post: state.postsById[ownProps.postId]
})
)(DeletePostModal)
C'est à vous de venir avec un ensemble d'accessoires qui <Modal>
peut accepter dans votre application, mais j'imagine que vous pourriez avoir plusieurs types d'auxiliaires modaux (p. ex. info modal, la confirmation modal, etc), et plusieurs styles pour eux.
De l'accessibilité et de Cacher un Clic à l'Extérieur ou Échapper à la Clé
La dernière partie importante sur les auxiliaires modaux est que, généralement, nous voulons cacher lorsque l'utilisateur clique sur l'extérieur ou les presses à s'Échapper.
Au lieu de vous donner des conseils sur la mise en œuvre de la présente, je suggère que vous venez de ne pas mettre en œuvre vous-même. Il est difficile de faire droit compte tenu de l'accessibilité.
Au lieu de cela, je vous suggère d'utiliser un accessible hors-the-shelf modal composant tel qu' react-modal
. Il est entièrement personnalisable, vous pouvez mettre ce que vous voulez à l'intérieur d'elle, mais elle gère l'accessibilité correctement de façon à ce que les personnes aveugles peuvent toujours utiliser votre modal.
Vous pouvez même terminer react-modal
dans votre propre <Modal>
qui accepte des accessoires spécifiques à vos applications et génère de l'enfant, de boutons ou d'autres contenus. C'est tout simplement les composants de!
D'Autres Approches
Il y a plus d'une façon de le faire.
Certaines personnes n'aiment pas le niveau de verbosité de cette approche et préfèrent avoir un <Modal>
de la composante qu'ils peuvent se rendre directement à l'intérieur de leurs composants avec une technique appelée "portails". Portails vous permettent d'effectuer le rendu d'un composant à l'intérieur de la vôtre alors qu' en fait il va rendre à un endroit prédéterminé dans les DOM, ce qui est très pratique pour les auxiliaires modaux.
En fait, react-modal
I lié à l'heure le fait déjà en interne donc, techniquement, vous n'avez même pas besoin de la calculer à partir du haut. Je trouve toujours agréable de découpler la modale je veux montrer à partir de la composante montrer, mais vous pouvez également utiliser react-modal
directement à partir de vos composants, et passez la plupart de ce que j'ai écrit ci-dessus.
Je vous encourage à considérer les deux approches, de les expérimenter et de choisir ce que vous trouver qui fonctionne le mieux pour votre application et à votre équipe.