簡體   English   中英

反應關閉父級的所有子模式

[英]React close all child modal from parent

我有以下樹的三個組件:

<Update>
  <ExpenseItem>
    <ExpenseItemModal>

Update 接受一組費用並為每項費用呈現一個 ExpenseItem 組件。 我正在使用鈎子來處理模態可見性。 正如您所料,我正在使用此模式來編輯費用屬性。

從 ExpenseItem 上的 useModal 鈎子導入切換方法以打開和關閉模式。 我期望的是在模態之外單擊並關閉它。 但是如果我有另一個 ExpenseItem 模式設置為 true,它會關閉當前,但它仍然會顯示另一個。 我想在模態之外單擊(可能在更新組件上)並一次關閉所有模態,以避免打開多個模態。 實際上我只想立即打開模態。

這些是以下組件:

上傳

import { useState, useEffect } from 'react';
import useModal from '../hooks/useModal';
import ExpenseItem from './expenseItem';
import axios from 'axios';

function Update({ data }) {
    useEffect(() => console.log('update component', expenses));
    const saveToDatabase = () => {
        axios.post('http://localhost:3001/expenses', expenses).then((res) => {
            console.log('data is saved to database');
        });
    };
    const { setIsShowing } = useModal();
    const closeModals = () => setIsShowing(false);
    const [ expenses, setExpenses ] = useState(data);
    return (
        <div>
            {expenses.map((expense, index) => {
                return <ExpenseItem key={index} index={index} expenses={expenses} setExpenses={setExpenses} />;
            })}
            <button onClick={() => saveToDatabase()}>Save</button>
        </div>
    );
}

export default Update;

費用項目

import useModal from '../hooks/useModal';
import EditExpenseModal from './editExpenseModal';

function ExpenseItem(props) {
    const { isShowing, toggle, setIsShowing } = useModal();
    let { description, date, credit, debit } = props.expenses[props.index];
    const updateValue = (expense, setExpenses, success) => {
        const expenses = [ ...props.expenses ];
        expenses.splice(props.index, 1, {
            ...expense
        });
        setExpenses(expenses);
        success();
    };
    return (
        <div>
            <div className="expense-box" onClick={toggle}>
                <p>{date}</p>
                <div className="expense-info">
                    <p className="expense-info--description">{description}</p>
                    <p className="expense-info--debit">{debit}</p>
                    <p className="expense-info--credit">{credit}</p>
                </div>
            </div>
            <EditExpenseModal
                isShowing={isShowing}
                hide={toggle}
                expense={props.expenses[props.index]}
                updateExpense={updateValue}
                setExpenses={props.setExpenses}
            />
            <style jsx>{`
                .expense-box {
                    width: 800px;
                    border: 1px solid black;
                    border-radius: 2px;
                    margin: 25px auto;
                    padding: 0 10px;
                }
                .expense-info {
                    display: flex;
                }
                .expense-info--description {
                    margin: 0 auto 0 0;
                }
                .expense-info--debit {
                    color: red;
                }
                .expense-info--credit {
                    color: green;
                }
            `}</style>
        </div>
    );
}

export default ExpenseItem;

編輯費用模式

import { useState, useEffect, Fragment } from 'react';
import { createPortal } from 'react-dom';

const EditExpenseModal = ({ expense, isShowing, hide, updateExpense, setExpenses }) => {
    const { description, date, credit, debit } = expense;
    useEffect(() => {
        document.body.style.overflow = 'hidden';
        return () => (document.body.style.overflow = 'unset');
    }, []);
    const [ expenseItem, setExpenseItem ] = useState({
        date,
        description,
        category: null,
        subcategory: null,
        credit,
        debit
    });
    const handleInputChange = (e) => {
        const { name, value } = e.target;
        setExpenseItem({ ...expenseItem, [name]: value });
    };
    return isShowing
        ? createPortal(
                <Fragment>
                    <div>
                        <div className="form">
                            <form>
                                <ul>
                                    <li className="form-inputs">
                                        <label>Date</label>
                                        <input type="text" name="date" defaultValue={date} onChange={handleInputChange} />
                                    </li>
                                    <li className="form-inputs">
                                        <label>Description</label>
                                        <input
                                            type="text"
                                            name="description"
                                            defaultValue={description}
                                            onChange={handleInputChange}
                                        />
                                    </li>
                                    <li className="form-inputs">
                                        <label>Category</label>
                                        <input type="text" name="category" onChange={handleInputChange} />
                                    </li>
                                    <li className="form-inputs">
                                        <label>Subcategory</label>
                                        <input type="text" name="subcategory" onChange={handleInputChange} />
                                    </li>
                                    <li className="form-inputs">
                                        <label>Credit</label>
                                        <input
                                            type="text"
                                            name="credit"
                                            defaultValue={credit}
                                            onChange={handleInputChange}
                                        />
                                    </li>
                                    <li className="form-inputs">
                                        <label>Debit</label>
                                        <input
                                            type="text"
                                            name="debit"
                                            defaultValue={debit}
                                            onChange={handleInputChange}
                                        />
                                    </li>
                                </ul>
                            </form>
                            <button onClick={() => updateExpense(expenseItem, setExpenses, hide)}>save</button>
                            <button onClick={hide}>close</button>
                        </div>
                        <style jsx>{`
                            .form {
                                background: grey;
                                display: flex;
                                flex-direction: column;
                                position: absolute;
                                height: 100vh;
                                top: 0;
                                right: 0;
                                width: 40%;
                            }
                            .form-inputs {
                                display: flex;
                                flex-direction: column;
                                list-style-type: none;
                                padding: 1rem 2rem;
                            }
                        `}</style>
                    </div>
                </Fragment>,
                document.body
            )
        : null;
};

export default EditExpenseModal;

使用模態鈎子

import { useState } from 'react';

const useModal = () => {
    const [ isShowing, setIsShowing ] = useState(false);

    function toggle() {
        setIsShowing(!isShowing);
    }

    return {
        isShowing,
        setIsShowing,
        toggle
    };
};

export default useModal;

我不介意改變這些模態結構以使其工作。

在這種情況下,為了避免這些情況,您可以編寫一個單獨的方法來關閉模態,

在 ExpenseItem.js 中

<EditExpenseModal
                isShowing={isShowing}
                hide={hideModal}  //instead of toggle
                ...
 >

並通過直接傳遞“false”值而不是使用來編寫 hideModal 方法來關閉模態! 操作員。 像這樣在 useModal Hook 中:

function hideModal() {
        setIsShowing(false);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM