Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从setState回调触发时,为什么ReactDom.render()返回null?_Javascript_Reactjs_React Dom - Fatal编程技术网

Javascript 从setState回调触发时,为什么ReactDom.render()返回null?

Javascript 从setState回调触发时,为什么ReactDom.render()返回null?,javascript,reactjs,react-dom,Javascript,Reactjs,React Dom,我遇到了react这种非常奇怪的行为,并在下面创建了一个简单的演示 其行为是,当我直接在第182行中执行this.renderPortal()时,我可以关闭对话框。但是,当您从setState回调执行此操作时,如下所示: return <div onClick={()=>{ // this.renderPortal() //worker fine this.setState({ a : 1 }, ()=>{ this.renderPortal()

我遇到了react这种非常奇怪的行为,并在下面创建了一个简单的演示

其行为是,当我直接在第182行中执行
this.renderPortal()
时,我可以关闭对话框。但是,当您从setState回调执行此操作时,如下所示:

return <div onClick={()=>{
  // this.renderPortal() //worker fine 
  this.setState({
    a : 1
  }, ()=>{
    this.renderPortal()
  })
}}> click me</div>
对话框{
高度:50px;
背景:白色;
边框:1px纯色灰色;
顶部:20px;
宽度:500px;
位置:绝对位置;
}
.内部对话{
宽度:100%;
身高:100%;
}
.按钮{
位置:绝对位置;
底部:0;
边框:1px纯色灰色;
}


原因很简单,虽然对话框本身是无状态的,但它是在呈现有状态组件时呈现的,因此,
ReactDom.render
会认为它是有状态的

绕过该问题的一个简单方法是替换:

this.setState({
    a : 1
  }, ()=>{
    this.renderPortal()
  })
})

这样您的组件就被认为是无状态的

完整代码:

让rootDialogContainer=document.createElement(“div”);
document.body.appendChild(rootDialogContainer);
函数createConfig(配置,默认值){
返回Object.assign(
{},
违约,
配置的类型==“字符串”{content:config}:config
);
}
类Modal扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
秀:真的
};
this.cancel=this.cancel.bind(this);
}
ok(){
如果(此.props.autoClose){
this.setState({show:false});
}
const{onOk,afterClose}=this.props;
onOk&&onOk();
后关闭();
}
取消{
if(this.mounted&&this.props.autoClose){
this.setState({show:false});
}
const{onCancel,afterClose}=this.props;
onCancel&&onCancel();
后关闭();
}
销毁{
这个.props.forceClose();
}
componentDidMount(){
这是真的
}
组件将卸载(){
此参数=错误
}
render(){
让DialogType=this.props.dialog | | dialog;
返回(
);
}
}
类对话框扩展了React.Component{
建造师(道具){
超级(道具)
}
renderDialogWrap(参数){
让{
contentElm,
onCancel
}=参数;
返回(
{contentElm}
取消
);
}
renderPortal(){
回来
}
render(){
让props=this.props;
让{
显示
类名,
标题
所容纳之物
onCancel=()=>{},
onOk=()=>{},
儿童
renderAsHiddenIfNotShow=false,
}=道具;
返回ReactDOM.createPortal(
{this.renderDialogWrap({
一旦取消,
contentElm:孩子们,
显示
renderAsHiddenIfNotShow
})}
,
文件正文
); 
}
}
Dialog.show=函数(参数){
const config=createConfig(参数{
秀:没错,
自动关闭:是的,
onOk:()=>{},
onCancel:()=>{}
});
config.content=config.content | | config.desc;
let container=rootDialogContainer
if(config.id){
设containerId=`wrapper`
container=document.getElementById(containerId)
如果(!容器){
容器=document.createElement('div')
container.setAttribute('id',containerId)
document.body.appendChild(容器)
}
}
config.forceClose=函数(){
ReactDOM.unmountComponentAtNode(容器);
};
config.afterClose=函数(){
config.autoClose&&config.forceClose();
};
返回ReactDOM.render(this.buildModal(config),container);;
};
类包装器扩展了React.Component{
建造师(道具){
超级(道具)
}
renderPortal(){
常数destroy=()=>{
this.myDialog.destroy();
};
this.myDialog=Dialog.show({
onOk:()=>{},
onCancel:摧毁,
一旦失去:毁灭,
自动关闭:错误,
内容:
试验

}); } render(){ 返回{ //this.renderPortal()//工作进程正常 这是我的国家({ a:1 }, ()=>{ setTimeout(()=>this.renderPortal(),1) }) }}>点击我 } } Dialog.buildModal=函数(配置){ 回来 }; 函数App(){ 返回( ); } const rootElement=document.getElementById(“根”); render(,rootElement)
对话框{
高度:500px;
背景:白色;
边框:1px纯色灰色;
顶部:20px;
宽度:500px;
位置:绝对位置;
}
.内部对话{
宽度:100%;
身高:100%;
}
.按钮{
位置:绝对位置;
底部:0;
边框:1px纯色灰色;
}


“…在此创建了一个简单的演示…”请确保问题中包含所有必要的代码。(这个问题没有,它甚至没有
ReactDom
[sic]调用。)您可以通过使用堆栈片段(
[]
工具栏按钮)来实现这一点。堆栈代码段支持React,包括JSX@T.J.Crowder如果仔细看,演示链接实际上已经连接好了。链接!=在问题中,这意味着你的链接在不久的将来将不再活跃,访问你的OP的每个人都不知道你指的是什么。那么,创建一个就可以了。@Blake创建一个。只是不明白为什么您提供的代码使对话框有状态?为什么在setstate回调中调用时不被认为是有状态的?当您调用setstate时:React将首先对状态应用更改,传播到状态(如果此状态更改导致其他更改),应用回调,再次传播,重新启动组件,验证状态是否已更改,如果已更改,则重新启动整个流程(我们尝试通过不更改回调中的状态来限制这种情况,从而使用上面提到的反模式)。在此过程中创建的任何组件都将被视为有状态组件。您要说的是,从setstate回调调用的对话框使其成为有状态组件??但这不是opp吗
this.setState({
    a : 1
  }, ()=>{
    setTimeout(() => {
      this.renderPortal()
    }, 1)
  })