使用 Bootstrap
<Modal />
组件时,当我对父组件进行回调时,我的入口页面会重新渲染,并触发我的 useEffect({...}, [])
-Hook,它应该只被调用一次,再次被调用,但我不知道为什么。
我的设置:NextJS、ReactJS、Bootstrap-React
Home() - Parent
:
export default function Home() {
//data and internal logic states, table-content, which rows are selected, is the data still loading, etc.
const [loading, setLoading] = useState(true);
const [dataZähler, setDataZähler] = useState<ZählerObjekt[]>([]);
const [dataProtokoll, setDataProtokoll] = useState<ProtokollEintrag[]>([]);
const [selectedRowZähler, setSelectedRowZähler] = useState(-1);
const [selectedRowProtokoll, setSelectedRowProtokoll] = useState(-1);
//View-Logic states, which table is shown, if modals should be seen, etc
const [showCreateZählerModal, setShowCreateZählerModal] = useState(false);
//on start, load both csv's into states
useEffect(() => {
fetch('/api/loadCsv')
.then((res) => res.json())
.then((data) => {
setDataZähler(data.dataZähler)
setDataProtokoll(data.DataProtokoll)
setLoading(false)
})
}, []);
//rendering logic, the page only needs the data to work, so thats all thats needed, otherwise, show an error and have the user restart
if (loading) return <p>loading ...</p>
if (!dataZähler) return <p>No data on counters was found!</p>
if (!dataProtokoll) return <p>No data on entries was found!</p>
return (
<div className="flex flex-col">
<table> /* contains data, that gets edited when the modal is used/calls its callback */ </table>
{/*Modal Div - all edit/Cancel/Save/Create/Delete modals go here*/}
<div>
<Modal size="lg" show={showCreateZählerModal} onHide={() => setShowCreateZählerModal(false)}>
<Modal.Header closeButton>
<Modal.Title>
Neuen Zähler hinzufügen:
</Modal.Title>
</Modal.Header>
<Modal.Body>
<CreateCounterPopUp data={dataZähler[0]} callback={(data) => {
if (data)
setDataZähler([...dataZähler, data]);
setShowCreateZählerModal(false);
}} />
</Modal.Body>
</Modal>
</div>
</div>
);
}
CreateCounterPopUp() - Child
:
interface CounterProps {
data: ZählerObjekt, //seed the PopUp
callback: ZählerCallback //(only requires a Zählerobjekt)
}
export function CreateCounterPopUp({ data, callback }: CounterProps) {
const [newCounter, setNewCounter] = useState(new ZählerObjekt());
function handleSpeichern() { //dont forget to set the id of the new object
setNewCounter({ ...newCounter, ...{ id: generateGenericObjectID(newCounter) } });
callback(newCounter);
}
function handleInputChange(field: string, event: ChangeEvent<HTMLInputElement>) {
const newState = { ...newCounter };
newState[field as keyof ZählerObjekt] = event.target.value;
setNewCounter(newState);
}
return (
<div>
<form>
{Object.entries(newCounter).slice(1).map((elem, idx) => {
return (
<Form.Group
className="mb-3" key={idx} controlId={elem[0]}
>
<Form.Label>{elem[0]}</Form.Label>
<Form.Control
as="textarea"
rows={2}
placeholder={"z.B. " + String(data[elem[0] as keyof ZählerObjekt])}
onChange={(e) => handleInputChange(elem[0], e as any)} />
</Form.Group>
);
})}
<div className="float-right">
<button onClick={handleSpeichern} className="bg-[#22c55e] border-[none] text-[white] text-center inline-block text-base rounded-[5px] px-5 py-3 my-2">Speichern</button>
</div>
</form>
</div>
);
}
我尝试将页面的大小减小到最重要的部分,但是任何人都可以告诉我为什么当模态使用回调时模态会触发完整的
Home()
重新渲染,而不是当其 onHide()
属性为打电话了?
错误是React还在后台调用了一些其他函数,因此崩溃了。
function handleSpeichern(event: React.MouseEvent<HTMLButtonElement>) {
event.preventDefault();
{...}
}
防止默认事件发生保存了代码。