【问题标题】:Create global modal that calls different fuctions创建调用不同函数的全局模态
【发布时间】:2021-10-15 07:43:01
【问题描述】:

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

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

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

【问题讨论】:

  • 您是否尝试过将相关函数作为道具发送给组件?
  • 问题是我想将 Modal 组件保留在我的应用程序的根级别,但我无法将函数提供给 modal 组件,因为它不能存储在减速器中,因为函数不是-可序列化。我想避免在每个组件中导入 Modal 并控制其状态(打开/关闭)
  • "我想避免在每个组件中导入 Modal 并控制其状态(打开/关闭)"。然后创建另一个使用模态的组件并让该组件控制状态并执行函数回调。然后可以将该组件导入您需要的地方。

标签: javascript reactjs redux react-context


【解决方案1】:

您可以定义 ModalProvider 并将其放在您的 ReduxProviderContextProvider 之后以使用状态(存储)值和操作。让我们用一些示例代码来演示一下,我指的是使用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之后才能使用状态对象。

通过定义正确的reduceractions来完成redux实现:

示例操作:

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>
    // ... 
)

解释: onCloseActiononOpenAction 与标题和描述相同,它们是字符串,但它们获得了 动作名称 并调度它。 由于无法对 store 中的函数进行消毒,因此可以将操作名称保存为字符串来解决问题。

【讨论】:

  • 感谢您的回复。如果我想让相同的模态在不同的地方执行不同的动作怎么办。理想的解决方案是调度一个包含类似 const handleOpenInfoModal = (title, description, action) =&gt; { dispatch(openModal({title, description, action })) } 的函数的对象,其中 action 是一个随机函数但不幸的是,这不是你可以用 Redux 或 Context 做的事情
  • 这是我的荣幸@AleksandrFomin。
  • 您为什么不在操作部分定义您的操作,然后在您的组件中导出并使用它们?将函数传递给 redux 存储(这是一个对象)是无用的,因为正确的方法是使用 dispatch 方法来调度正确的操作。您还可以在减速器@AleksandrFomin 中为您的模态组件定义具有不同效果的一千个动作
  • 我猜您需要将一些函数传递给模态以放置在模态内部,并通过用户与模态本身的交互来执行一些操作。它是否正确? @AleksandrFomin
  • 不幸的是,您的调度程序函数无法传递动作。它可以通过使用其他页面/组件中的“模态组件”来实现。但是您可以在模态组件中定义一些功能并使用一些属性来限制使用它们@AleksandrFomin
猜你喜欢
  • 2018-07-03
  • 2019-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 2015-02-23
相关资源
最近更新 更多