[英]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.