我知道这个问题以前曾被问过,但答案似乎总是暗示着与这种情况无关的问题,我只是看不到。
我有一个父组件,该组件将属性传递给子组件的状态。根据此传递的属性的值,子代最初是否显示其视图。这是我思考 React的方式:
当父(或一般组件)的状态更改时,它将重新呈现。重新渲染后,它的所有子代都再次收到其道具(即,是否也调用了子代的构造函数?)。但这显然不是此示例中的工作方式。
class FileListTable extends React.Component
{
constructor(props)
{
super(props);
this.state = {
showModal: false
};
this.showSelectFolderModal = this.showSelectFolderModal.bind(this);
}
showSelectFolderModal()
{
this.setState({ showModal: true });
}
render()
{
console.log("Rendering table with showModal = " + this.state.showModal);
return (
<div>
<table id="files-table" class="table">
<tr>
<td>
...
<span class="float-right">
<FileActionMenu
showSelectFolderModal={ this.showSelectFolderModal } />
</span>
</td>
</tr>
</table>
<SelectFolderModal
show={ this.state.showModal }/>
</div>
);
}
}
FileActionMenu
子组件:class FileActionMenu extends React.Component
{
constructor(props)
{
super(props);
}
render()
{
return (
<div class="dropdown">
<button class="btn dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
...
</button>
<div class="dropdown-menu dropdown-menu-right">
<button class="dropdown-item" type="button" onClick={ () => this.props.showSelectFolderModal() }>...</button>
</div>
</div>
);
}
}
SelectFolderModal
子组件:class SelectFolderModal extends React.Component
{
constructor(props)
{
super(props);
console.log("Received props from table");
console.log(this.props);
this.state = { show: this.props.show };
}
closeModal()
{
this.setState({ show: false });
// do something post close
}
render()
{
console.log("Rendering modal with show status: " + this.state.show);
return (
<div id="select-folder-modal" class="modal { this.state.show ? 'show' }" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" onClick={ this.closeModal }>...</button>
</div>
</div>
</div>
</div>
);
}
}
我的初始控制台输出是这样:
具有showModal = false的渲染表
桌上收到的道具
{show:false}
显示状态为false的渲染模态
好的,这很有道理。但是,当我单击FileActionMenu
中的按钮时,会得到以下输出:
具有showModal = true的渲染表
显示状态为false的渲染模态
因此,当父母正在更新时,父母的状态不会作为道具传递给孩子!但是我认为这是这样的,有人可以帮我一下吗?
答案 0 :(得分:0)
不,您的想法不正确。组件的构造函数不应在每次渲染/更新时都被调用。一旦被安装,它们就会被呼叫。
回到您的示例,SelectFolderModal
应该是无状态的。实际上,父级维护应用程序的“状态”。没有什么可以阻止您在render
方法中使用“道具”:
在SelectFolderModal
的render方法中,请使用props
而不是state
,因为该组件应该是无状态的。
该组件还需要另一个道具:closeModal
,哪个父级应该传入回调方法以通过设置状态来关闭模式。
this.setState({ showModal: false });
答案 1 :(得分:0)
您的代码中有一个小错误。您正在将show
中的父道具(constructor
道具)设置为子状态,该状态最初会起作用。然后,每次父项道具更改时,子项组件都通过shouldComponentUpdate
接收更改的道具。
因此,在您的代码中,您可以像这样访问父项(show
):
showSelectFolderModal
的函数,将show
的值更改为false
closeModal
函数。
class FileListTable extends React.Component {
constructor(props) {
super(props);
this.state = {
showModal: false
};
this.showSelectFolderModal = this.showSelectFolderModal.bind(this);
this.hideSelectFolderModal = this.hideSelectFolderModal.bind(this);
}
showSelectFolderModal() {
this.setState({ showModal: true });
}
hideSelectFolderModal() {
this.setState({ showModal: false });
}
render() {
console.log(this.state);
return (
<div>
<table id="files-table" class="table">
<tr>
<td>
Main Table
<span class="float-right">
<FileActionMenu
showSelectFolderModal={this.showSelectFolderModal}
/>
</span>
</td>
</tr>
</table>
<SelectFolderModal
show={this.state.showModal}
hideSelectFolderModal={this.hideSelectFolderModal}
/>
</div>
);
}
}
class FileActionMenu extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div class="dropdown">
<div class="dropdown-menu dropdown-menu-right">
<button
class="dropdown-item"
type="button"
onClick={() => this.props.showSelectFolderModal()}
>
event button
</button>
</div>
</div>
);
}
}
class SelectFolderModal extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log(this.props.show);
return (
<div
id="select-folder-modal"
class={`modal ${this.props.show ? "show" : ""}`}
tabIndex="-1"
role="dialog"
>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">...</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-dismiss="modal"
onClick={() => this.props.hideSelectFolderModal()}
>
hide
</button>
</div>
</div>
</div>
</div>
);
}
}
ReactDOM.render(<FileListTable />, document.getElementById("root"));
这是现场demo
希望它会有所帮助:)
答案 2 :(得分:0)
小的代码更改可能会帮助您解决问题。
请按如下所示更改您的回调函数:
showSelectFolderModal()
{
this.setState({ showModal: !this.state.showModal });
}
此外,将此功能作为道具发送到SelectFolderModal组件。因为您可以调用此函数而不是调用closeModal函数。
请避免使用多个状态来执行单个操作。按照代码在SelectFolderModal中使用状态变量毫无意义。