简体   繁体   English

使用 React 组织/管理多个模式的“正确”方式

[英]"Right" way to organize/manage multiple modals with React

I'm in the process of teaching myself React and have been constructing a simple budgeting system to do it.我正在自学 React,并且一直在构建一个简单的预算系统来做到这一点。 I'm using React-Bootstrap for the design and have built a few different modals to handle certain functionality in my app.我正在使用 React-Bootstrap 进行设计,并构建了一些不同的模式来处理我的应用程序中的某些功能。

The app works just fine, however as a developer I feel that things could be tightened up quite a bit in terms of how my code is designed.该应用程序运行良好,但是作为开发人员,我觉得就我的代码设计方式而言,事情可能会收紧一些。

One of the places that could be designed better is how I'm handling multiple modals.可以设计得更好的地方之一是我如何处理多个模态。 As you can see I currently have 4 modals, all of which are being passed a variety of props (that are also passed into BudgetContainer).如您所见,我目前有 4 个模态,所有这些都被传递了各种道具(也被传递到 BudgetContainer)。 Some of this functionality (such as "setOpenModal") is necessary due to the fact that I need to be able to control which modal is opened from various places within the app.由于我需要能够控制从应用程序中的各个位置打开哪个模式,因此其中一些功能(例如“setOpenModal”)是必需的。

However this design results in having to pass a ton of props back and forth all across my app in order get all the data/functions to be present where I need it to be.然而,这种设计导致必须在我的应用程序中来回传递大量道具,以便让所有数据/功能出现在我需要的地方。 After some research I see that this is what is referred to as 'prop-drilling'.经过一些研究,我发现这就是所谓的“螺旋钻”。

I've looked into some other methods such as some sort of global state-management approach (such as Redux), but these all seem like a very heavy-handed solution.我研究了其他一些方法,例如某种全局状态管理方法(例如 Redux),但这些似乎都是一个非常严厉的解决方案。

I also considered moving the location of the modals onto the same component that triggers them to show, however then I end up with random modals scattered all throughout the app rather than being in one area.我还考虑将模态框的位置移动到触发它们显示的同一组件上,但是最终我会发现随机模态框分散在整个应用程序中,而不是在一个区域中。

Is there some design pattern I'm overlooking here?我在这里忽略了一些设计模式吗? I'm a just a React newb?我只是一个 React 新手? I feel like modals are a common enough feature in web development that a solution must already be present.我觉得模态是 web 开发中足够常见的功能,必须已经存在解决方案。

import React, { useState } from 'react'
import { Row, Col } from 'react-bootstrap-v5'
import { useAsync } from 'react-async'

import budgetApi from '@/api/budgetApi.js'
import { transactionDefault } from '@/objectDefaults/transaction.js'
import BudgetContainer from './components/BudgetContainer.js'
import Cashflow from './components/Cashflow.js'
import UnbudgetedTransactions from './components/UnbudgetedTransactions.js'

import BudgetModal from '@/common/modals/BudgetModal'
import DeleteBudgetModal from '@/common/modals/DeleteBudgetModal'
import TransactionDetailModal from '@/common/modals/TransactionDetailModal'
import TransactionSplitModal from '@/common/modals/TransactionSplitModal'

function BudgetContent() {
    const [activeBudget, setActiveBudget] = useState({})
    const [activeTransaction, setActiveTransaction] = useState(transactionDefault)
    const [activeDate, setActiveDate] = useState(new Date())
    const [openModal, setOpenModal] = useState('')

    // Retrieve the budgeting data
    const { data, error, isPending, run } = useAsync({ 
        promiseFn: budgetApi.getPromise,
        deferFn: budgetApi.getDefer,
        watch: activeDate,
        onResolve: (resolvedData) => {
            // Update the activeBudget's data
            let freshActiveBudget = resolvedData.data.budgeted_transactions.filter(
                freshBudget => freshBudget.id == activeBudget.id
            )
            setActiveBudget(freshActiveBudget[0] ?? {})
        },
        // PHP's Carbon library can easily parse ISO dates
        period: activeDate.toISOString()
    })

    return (
        <div>
            <Row>
                <Col md={7}>
                    <BudgetContainer
                        budgets={data && data.data.budgeted_transactions}
                        activeDate={activeDate}
                        setActiveDate={setActiveDate}
                        isPending={isPending}
                        activeBudget={activeBudget}
                        setActiveBudget={setActiveBudget}
                        setActiveTransaction={setActiveTransaction}
                        setOpenModal={setOpenModal}
                    />
                </Col>
                <Col md={5}>
                    <Row>
                        <Col>
                            <Cashflow />
                        </Col>
                    </Row>
                    <Row className="pt-2">
                        <Col>
                            <UnbudgetedTransactions
                                transactions={data && data.data.unbudgeted_transactions}
                                setOpenModal={setOpenModal}
                                setActiveTransaction={setActiveTransaction} 
                            />
                        </Col>
                    </Row>
                </Col>
            </Row>

            {<TransactionDetailModal
                show={openModal == 'transaction_detail'}
                setOpenModal={setOpenModal}
                activeTransaction={activeTransaction}
                refreshBudgets={run}
                budgets={data && data.data.budgeted_transactions}
            />
            <TransactionSplitModal
                show={openModal == 'transaction_split'}
                setOpenModal={setOpenModal}
                activeTransaction={activeTransaction} 
            />
            <BudgetModal
                show={openModal == 'create_budget'}
                setOpenModal={setOpenModal}
                refreshBudgets={run}
                activeBudget={activeBudget}
            />
            <DeleteBudgetModal
                show={openModal == 'delete_budget'}
                setOpenModal={setOpenModal}
                refreshBudgets={run}
                activeBudget={activeBudget}
                setActiveBudget={setActiveBudget}
            />}
        </div>
    )
}

export default BudgetContent

In the end I just chose to use React's Context API to share the information needed by the modals between elements and avoid prop drilling.最后我只是选择使用 React 的 Context API 来共享元素之间模态所需的信息,避免道具钻探。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM