我想创建一个灵活的模式包装器,我可以在其中放置交互式组件。在这种情况下,我想将输入放入模态中,这会影响表单的整体状态。
形式:
const [formInfo, setFormInfo] = useState({});
const [modalMetadata, setModalMetadata] = useState({});
const [modalContents, setModalContents] = useState({});
const [modalShow, setModalShow] = useState(false);
...
return <ModalWrapper modalIsOpen={modalShow} closeModal={() => {setModalShow(false)}} contents={modalMetadata}>
{modalContents}
</ModalWrapper>
<button onClick={
setModalShow(true);
setModalMetadata({
contentLabel: "",
title: "Are you sure?",
buttons: [
{
onClick: () => setModalShow(false),
content: "Cancel"
},
{
onClick: () => submitForm(),
content: "Confirm"
}
],
})}
setModalContents(<div><h4>blahblahblah</h4>
{inputTitles.map((k) => <div key={"field-"+ k}>
<div>
<input
type='text'
onChange={i => {
console.log(i.target.value);
console.log(formInfo)
console.log({...formInfo, ["field-" + k]: i.target.value})
setFormInfo( formInfo => {return {...formInfo, ["field-" + k]: i.target.value}})
}}
/>
<span></span>
</div>
<label>${k}</label>
</div>)}
</div>);
}>
包装纸:
import Modal from 'react-modal';
export default function ModalWrapper({ modalIsOpen, closeModal, contents, children }) {
return (
<div>
<Modal
isOpen={modalIsOpen}
onRequestClose={closeModal}
contentLabel={contents.contentLabel}
>
<h2>{contents.title}</h2>
{children}
<div>
{(contents?.buttons ?? []).map((i, idx) => <button className={i.className} key={"button-" + idx} onClick={i.onClick}>{i.content}</button>) }
</div>
</Modal>
</div>
);
}
(为简洁起见,删除了 CSS 和不相关的变量)
虽然大多数调试控制台语句返回预期值并且按钮按计划工作,但我注意到
formInfo
没有更新。 setFormInfo
在模式内容中未按预期工作的原因是什么?
我在网上查找,发现了该机制工作的多个示例(1、2),它们将通过另一个组件的子组件传递 React hook,但我无法复制我遇到的错误。对 React Children 和 React hooks 的本质有更好了解的人会知道出了什么问题吗?
[2] 我尝试将 onChange 属性添加到作为独立输入元素和 Avatar 元素给出的示例中,但它按计划工作。
React 中状态的工作很多时候有点令人困惑。 useState 钩子更新状态变量,其更新值将在组件的下一次渲染中可用。
例如,如果你这样做
const [text, setText] = useState("");
setText("text");
console.log(text);
console.log 会将文本值打印为空字符串。在下一个渲染中,您将能够在控制台中看到“文本”。
设置要传递给子组件的状态变量的最佳方法是在 useEffect 挂钩中设置它们。