A ideia por trás deste tutorial é a criação de um código dinâmico de modais em React js com a ajuda do Context. Aqui está um exemplo do que eu estou falando.
Componente da Modal
O componente da modal que é um Portal , recebe do Context o apelido da modal que deve ter o estado alterado e a sua ação que é abrir ou fechar, e do seu componente pai ela recebe o children(jsx a ser renderizado) e o apelido do mesmo, para verificar se é essa modal mesmo que o evento está chamando.
import React, { useContext } from "react";
import ReactDOM from "react-dom";
import { ModalContext } from "../context/modal-context";
import { ModalContainer } from "./modal-styles";
interface ModalContextProps {
isShowing: any;
handleModal: any;
}
const Modal = ({children, alias}: any) => {
const { isShowing } = useContext<ModalContextProps>(ModalContext);
let arrayModal;
isShowing.forEach((modal: any) => {
if (modal.action === 'open' && alias === modal.alias) {
arrayModal = (<ModalContainer>{children}</ModalContainer>
);
}
});
return isShowing.length ? ReactDOM.createPortal(arrayModal, document.body) : null;
};
export default Modal;
Página
O página é responsável por enviar o evento que irá chamar ás modais, ela também é responsável por conter o componente que a modal vai renderizar, mencionado anteriormente o children, também é necessário que todo o componente de modal utilizado tenha o seu apelido declarado, como forma de identificação.
import React, { useContext } from 'react';
import { Container} from './home-styles';
import { ModalContext } from '../../context/modal-context';
import Modal from "../../components/modal";
import FirstPortal from "../portal/first-portal/first-portal";
import SecondPortal from '../portal/second-portal/second-portal';
import ThirdPortal from '../portal/third-portal/third-portal';
const FormDynamic: React.FC = () => {
const { handleModal } = useContext(ModalContext);
return (
<Container>
<button
onClick={() => handleModal('open', 'first-modal')}>
Abrir primeira modal
</button>
<button
onClick={() => handleModal('open', 'second-modal')}>
Abrir segunda modal
</button>
<button
onClick={() => handleModal('open', 'third-modal')}>
Abrir terceira modal
</button>
<Modal alias='first-modal'>
<FirstPortal/>
</Modal>
<Modal alias='second-modal'>
<SecondPortal/>
</Modal>
<Modal alias='third-modal'>
<ThirdPortal/>
</Modal>
</Container>
);
}
export default FormDynamic;
Conteúdo da modal
O conteúdo a ser renderizado na modal contém tudo o que deve ser exibido ao abrir a modal.
import React, { useContext } from 'react';
import { Portal } from '../portal-styles';
import { RiCloseLine } from "react-icons/ri";
import { ModalContext } from '../../../context/modal-context';
const FirstPortal: React.FC = () => {
const { handleModal } = useContext(ModalContext);
return (
<Portal>
<RiCloseLine onClick={() => handleModal('close', 'first-modal')}/>
<h1>Primeira Modal</h1>
<span>😃</span>
</Portal>);
}
export default FirstPortal;
Hooks
O hook useModal é reponsável por armazenar os estados e as funções que irão acionar a modal.
import { useState } from "react";
const useModal = () => {
let [isShowing, setIsShowing] = useState<Array<any>>([]);
const handleModal = (action:string, alias: string) => {
if (action === 'close') {
const newIsShowing = isShowing.filter(
modal => modal.alias !== alias
);
setIsShowing(newIsShowing);
} else {
setIsShowing([...isShowing, { action: 'open', alias }]);
}
};
return {handleModal, isShowing };
};
export default useModal;
Context
O Context é responsável por ser um intermediário entre os estados e funções armazenados no useModal com o componentes que deve utilizá-lo.
import React, { ContextType, createContext, ReactChild, ReactChildren } from "react";
import useModal from "../hooks/useModal";
interface Props {
children: ReactChild | ReactChildren;
}
export const ModalContext = createContext<any>({});
let ModalProvider = ({ children }: Props) => {
const { handleModal, isShowing } = useModal();
return (
<ModalContext.Provider value={{ handleModal, isShowing }}>
{children}
</ModalContext.Provider>
);
};
export default ModalProvider;
Top comments (0)