React:如何从父组件在子组件中设置状态?
React: How to setState in child component from parent component?
我是 React 的新手,我正在尝试设置一个 Bootstrap 模式来显示警报消息。
在我的父 App.js 文件中,我有一个错误处理程序,它向 Modal.js 组件发送一个触发模态显示的道具,例如:
在 App.js:
function App() {
const [modalShow, setModalShow] = useState(false);
// Some other handlers
const alertModalHandler = (modalMessage) => {
console.log(modalMessage);
setModalShow(true);
}
return (
// Other components.
<AlertModal modalOpen={modalShow}/>
)
}
在 Modal.js 上:
import React, { useState } from "react";
import Modal from "react-bootstrap/Modal";
import "bootstrap/dist/css/bootstrap.min.css";
const AlertModal = (props) => {
const [isOpen, setIsOpen] = useState(false);
if (props.modalOpen) {
setIsOpen(true);
}
return (
<Modal show={isOpen}>
<Modal.Header closeButton>Hi</Modal.Header>
<Modal.Body>asdfasdf</Modal.Body>
</Modal>
);
};
export default AlertModal;
但是,这不起作用。我收到错误:
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
如果我把Modal组件改成'dumb'组件,直接使用prop,例如:
const AlertModal = (props) => {
return (
<Modal show={props.modalOpen}>
<Modal.Header closeButton>Hi</Modal.Header>
<Modal.Body>asdfasdf</Modal.Body>
</Modal>
);
};
它确实有效,但我也想在 Modal.js 组件级别更改 show/hide 状态,例如,有一些东西可以处理那里的模态关闭按钮。
我不明白为什么会这样?
这是否意味着我必须在父 App.js 级别处理模态关闭功能?
编辑 - 完整 app.js 内容
import React, { useState } from 'react';
import './App.css';
import 'bootstrap/dist/css/bootstrap.css';
import AddUserForm from './components/addUserForm';
import UserList from './components/userList';
import AlertModal from './components/modal';
function App() {
const [users, setUsers] = useState([]);
const [modalShow, setModalShow] = useState(false);
const addPersonHandler = (nameValue, ageValue) => {
console.log(nameValue, ageValue);
setUsers(prevUsers => {
const updatedUsers = [...prevUsers];
updatedUsers.unshift({ name: nameValue, age: ageValue });
return updatedUsers;
});
};
const alertModalHandler = (modalMessage) => {
console.log(modalMessage);
setModalShow(true);
}
let content = (
<p style={{ textAlign: 'center' }}>No users found. Maybe add one?</p>
);
if (users.length > 0) {
content = (
<UserList items={users} />
);
}
return (
<>
<div className="container">
<div className="row">
<div className="col-md-6 offset-md-3">
<AddUserForm onAddPerson={addPersonHandler} fireAlertModal={alertModalHandler}/>
</div>
</div>
<div className="row">
<div className="col-md-6 offset-md-3">
{content}
</div>
</div>
</div>
<AlertModal modalOpen={modalShow}/>
</>
);
}
export default App;
如果您已经将名为 modalShow 的状态发送到 AlertModal 组件,则没有理由使用另一个具有相同功能的状态作为 isOpen.
每当 modalShow 改变时,它会导致 AlertModal 组件的 re-render 因为你改变了它的状态,然后在里面如果 prop 为真,则设置另一个状态,当您设置 isOpen 时,会导致另一个不需要 re-render。然后,在每个 re-render 上,如果 props.showModal 没有改变(并且仍然是真的),你会一次又一次地触发 setIsOpen。
如果你想控制 AlertModal 中的模态 open/close 我会这样做:
<AlertModal modalOpen={modalShow} setModalOpen={setModalShow}/>
将showModal状态的set函数传递给modal组件,然后随意使用。例如,在 onClick 处理程序中。
modal.js:
import React, { useState } from "react";
import Modal from "react-bootstrap/Modal";
import "bootstrap/dist/css/bootstrap.min.css";
const AlertModal = (props) => {
const onClickHandler = () => {
props.setModalOpen(prevState => !prevState)
}
return (
<Modal show={props.modalOpen}>
<Modal.Header closeButton>Hi</Modal.Header>
<Modal.Body>asdfasdf</Modal.Body>
</Modal>
);
};
export default AlertModal;
在你的modal.js
你应该把
if (props.modalOpen) {
setIsOpen(true);
}
在 useEffect 中。
React.useEffect(() => {if (props.modalOpen) {
setIsOpen(true);
}}, [props.modalOpen])
你永远不应该那样调用 setState
。如果你这样做,每个渲染都会 运行 并触发另一个渲染,因为你改变了状态。您应该将 setModalShow
与 if 子句一起放在 useEffect
中。例如:
useState(() => {
if (modalOpen) {
setIsOpen(true);
}
}, [modalOpen])
请注意,我还从 props
中重构了 modalOpen
。这样 useEffect
将仅在 modalOpen
更改时 运行。
我是 React 的新手,我正在尝试设置一个 Bootstrap 模式来显示警报消息。
在我的父 App.js 文件中,我有一个错误处理程序,它向 Modal.js 组件发送一个触发模态显示的道具,例如:
在 App.js:
function App() {
const [modalShow, setModalShow] = useState(false);
// Some other handlers
const alertModalHandler = (modalMessage) => {
console.log(modalMessage);
setModalShow(true);
}
return (
// Other components.
<AlertModal modalOpen={modalShow}/>
)
}
在 Modal.js 上:
import React, { useState } from "react";
import Modal from "react-bootstrap/Modal";
import "bootstrap/dist/css/bootstrap.min.css";
const AlertModal = (props) => {
const [isOpen, setIsOpen] = useState(false);
if (props.modalOpen) {
setIsOpen(true);
}
return (
<Modal show={isOpen}>
<Modal.Header closeButton>Hi</Modal.Header>
<Modal.Body>asdfasdf</Modal.Body>
</Modal>
);
};
export default AlertModal;
但是,这不起作用。我收到错误:
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
如果我把Modal组件改成'dumb'组件,直接使用prop,例如:
const AlertModal = (props) => {
return (
<Modal show={props.modalOpen}>
<Modal.Header closeButton>Hi</Modal.Header>
<Modal.Body>asdfasdf</Modal.Body>
</Modal>
);
};
它确实有效,但我也想在 Modal.js 组件级别更改 show/hide 状态,例如,有一些东西可以处理那里的模态关闭按钮。
我不明白为什么会这样?
这是否意味着我必须在父 App.js 级别处理模态关闭功能?
编辑 - 完整 app.js 内容
import React, { useState } from 'react';
import './App.css';
import 'bootstrap/dist/css/bootstrap.css';
import AddUserForm from './components/addUserForm';
import UserList from './components/userList';
import AlertModal from './components/modal';
function App() {
const [users, setUsers] = useState([]);
const [modalShow, setModalShow] = useState(false);
const addPersonHandler = (nameValue, ageValue) => {
console.log(nameValue, ageValue);
setUsers(prevUsers => {
const updatedUsers = [...prevUsers];
updatedUsers.unshift({ name: nameValue, age: ageValue });
return updatedUsers;
});
};
const alertModalHandler = (modalMessage) => {
console.log(modalMessage);
setModalShow(true);
}
let content = (
<p style={{ textAlign: 'center' }}>No users found. Maybe add one?</p>
);
if (users.length > 0) {
content = (
<UserList items={users} />
);
}
return (
<>
<div className="container">
<div className="row">
<div className="col-md-6 offset-md-3">
<AddUserForm onAddPerson={addPersonHandler} fireAlertModal={alertModalHandler}/>
</div>
</div>
<div className="row">
<div className="col-md-6 offset-md-3">
{content}
</div>
</div>
</div>
<AlertModal modalOpen={modalShow}/>
</>
);
}
export default App;
如果您已经将名为 modalShow 的状态发送到 AlertModal 组件,则没有理由使用另一个具有相同功能的状态作为 isOpen.
每当 modalShow 改变时,它会导致 AlertModal 组件的 re-render 因为你改变了它的状态,然后在里面如果 prop 为真,则设置另一个状态,当您设置 isOpen 时,会导致另一个不需要 re-render。然后,在每个 re-render 上,如果 props.showModal 没有改变(并且仍然是真的),你会一次又一次地触发 setIsOpen。
如果你想控制 AlertModal 中的模态 open/close 我会这样做:
<AlertModal modalOpen={modalShow} setModalOpen={setModalShow}/>
将showModal状态的set函数传递给modal组件,然后随意使用。例如,在 onClick 处理程序中。
modal.js:
import React, { useState } from "react";
import Modal from "react-bootstrap/Modal";
import "bootstrap/dist/css/bootstrap.min.css";
const AlertModal = (props) => {
const onClickHandler = () => {
props.setModalOpen(prevState => !prevState)
}
return (
<Modal show={props.modalOpen}>
<Modal.Header closeButton>Hi</Modal.Header>
<Modal.Body>asdfasdf</Modal.Body>
</Modal>
);
};
export default AlertModal;
在你的modal.js
你应该把
if (props.modalOpen) {
setIsOpen(true);
}
在 useEffect 中。
React.useEffect(() => {if (props.modalOpen) {
setIsOpen(true);
}}, [props.modalOpen])
你永远不应该那样调用 setState
。如果你这样做,每个渲染都会 运行 并触发另一个渲染,因为你改变了状态。您应该将 setModalShow
与 if 子句一起放在 useEffect
中。例如:
useState(() => {
if (modalOpen) {
setIsOpen(true);
}
}, [modalOpen])
请注意,我还从 props
中重构了 modalOpen
。这样 useEffect
将仅在 modalOpen
更改时 运行。