首页 > 解决方案 > 创建调用不同功能的全局模态

问题描述

例如,我有一个带有对话框的模式来确认保存更改。此模式用于多个组件,但它必须根据组件调用不同的函数。它调用的函数存在于组件内部。

最好创建一个可重用的全局模态组件(使用 Redux 或 React Context),它可以根据使用的屏幕接受不同的功能

我知道你不能在减速器中存储不可序列化的值,所以我想知道是否有一种优雅的方法来处理这种情况而不必在每个单独的组件中导入模态?

标签: javascriptreactjsreduxreact-context

解决方案


您可以定义 aModalProvider并将其放在您的ReduxProvideror之后ContextProvider使用状态(存储)值和操作。让我们用一些示例代码来演示它,我指的是使用Redux,但您可以使用ContextApi相同的。

首先,定义一个通用/全局模态提供者

import React from 'react';
import {useSelector} from 'react-redux';

const ModalProvider = ({children}) => {
  const modal = useSelector(state => state.modal)

  return(
    <ModalComponent isVisible={modal.isVisible} title={modal.title} >
      {children}
    </ModalComponent>
  )
}

export default ModalProvider;

注意: ModalComponent是一个示例模态组件,它提供标题、模态状态和您在应用程序中可能需要的其他选项。

现在,是时候ModalProvider在根组件中使用了:

import ReduxProvider from 'path/to/your/redux/provider';
import ModalProvider from 'path/to/your/modal/proivder';

const App = () => (
  <ReduxProvider store={store} >
    // put the ModalProvider after the ReduxProvider
    <ModalProvider>
      // your other providers, toasts, routes ...
    </ModalProvider>
  </ReduxProvider>
)

export default App;

注意: ModalProvider必须放在ReduxProvider消费状态对象之后。

通过定义正确的reducerand来完成 redux 的实现actions

示例操作:

const OPEN_MODAL = "OPEN_MODAL";
const CLOSE_MODAL = "CLOSE_MODAL";

const openModal = (modalData) => ({type: OEPN_MODAL, payload: modalData})
const closeModal = () => ({type: CLOSE_MODAL})

并且,减速器:

const initialState = {
  isVisible: false,
  title: "",
  description: "",
  // and so on for the rest of details depend on your application
}

const modalReducer = (state=initialState, action) => {
  switch(action.type) {
    case OPEN_MODAL:
      return {
        ...state,
        isVisible: true,
        title: action.payload.title,
        description: action.payload.description
      }
    case CLOSE_MODAL: {
      return {
        ...state,
        isVisible: false,
        title: "",
        description: ""
      }
     default: 
       return state;
    }
  }
}

重要的提示:

您可能需要一个toggleModal动作或其他动作来控制您的模态行为,因此请按照您的意愿实施它们。

最后,使用dispatch方法在组件/页面中调度正确的操作。

import React from 'react';
import {useDispatch} from 'react-redux';

const SampleComponet = () => {
  const dispatch = useDispatch();

  const handleOpenInfoModal = (title, description) => {
     dispatch(openModal({title, description}))
  }

  return(
    <div>
      <button onClick={() => handleOpenInfoModal("the info modal", "some description to display in the modal body")}>
         More Info
      </button>
    </div>
  )
}

更新

要传递自定义方法和函数,ModalCompnent您可以使用一种棘手的方法:

里面ModalComponent

const dispatch = useDispatch();

handleOnclose = () => {
  dispatch({tye: onCloseAction})
}

hadnleOpenClose = () => {
  dispatch({type: onOpenAction})
}

return(
  <div>
    <p>{title}</p>
    <p>{description}</p>
    <button onClick={handleOnClose}> CLOSE </button>
    <button onClick={handleOnOpen}> OPEN </button>
    // ... 
)

解释: onCloseAction and 和onOpenActiontitle 和description 一样,都是字符串,但是他们得到了action 的名字并且dispatch 了。由于您无法对商店中的功能进行消毒,因此您可以保存作为字符串的操作名称来解决问题。


推荐阅读