2016-11-30 76 views
0

我有这个strage情况下,也许我失踪如何反应componentDidMount的作品,也许这是一个奇怪的行为(右知道我不能提供一个真正的小提琴与jQuery插件的东西,但我敢肯定的问题比插头本身更宽)。为什么componentDidUpdate看不到新插入的dom节点?

var Hello = React.createClass({ 
    getInitialState() { 
    return {content: '<div id="target">ciao!</div>'} 
    }, 

    componentDidMount() { 
    const target = $('#target').init(); 
    this.target = target; 
    }, 

    componentWillReceiveProps(nextProps) { 
    if (condition) { 
     this.target.destroy(); // this remove even the DOM node 
    } 
    }, 

    componentDidUpdate() { 
    const target = $('#target').init(); // HERE PROBLEM! can't find the #target element 
    this.target = target; 
    } 

    render: function() { 
    return <div>Hello {this.state.content}</div>; 
    } 
}); 

我不明白为什么后'condition'是真实和DOM节点都通过插件破坏,componentDidUpdate没有找到#target,在我的脑海里应该是“重新渲染”在componentWillReceiveProps之后的第一个渲染中。我希望在那里,因为它从最初的状态读取它永远不会改变。

我错过了什么?

+0

你不能呈现原始的HTML一样,不使用恰当地命名为['dangerouslySetInnerHtml'(https://facebook.github.io/react/docs/dom-elements.html#dangerouslysetinnerhtml)。 –

+0

@JoeClay并非如此。无论如何,我试过,不改变任何东西.. – ciaoben

回答

0

在React中,您不应该在componentDidMount()生命周期方法中执行this.setState(),因为它会导致布局抖动。 查看更多关于布局在这里筹码:https://blog.idrsolutions.com/2014/08/beware-javascript-layout-thrashing/

原因是,this.setState()导致重新呈现(调用render()两次)。而这在实际的渲染方法发生一次在componentDidMount()一次。你应该找到一个方法来消除从componentDidMountsetState()和你的问题可能得到解决。作为初始尝试,我会将this.setState()移动到componentWillMount()方法内

+0

是的,你的权利,其实我没有使用的setState,但“此”对象settig模式,我将改写例子!无论如何,这不是问题 – ciaoben

+0

你的'componentDidMount()'中的'this.setState({target:target})'如何?尝试移动'componentWillMount()' –

+0

mmmm内部我认为你不清楚问题。如果我将它移动到WillMount的DOM节点不在那里,所以我不能绑定任何jQuery插件 – ciaoben

1

由于您正在使用jQuery操作react元素(this.state.content),这使得React无法检测到呈现内容的更改。所以,当你渲染它第一次

  1. componentDidUpdate具有初始状态,完全呈现组件,包括#target
  2. $('#target').init()之后被调用时,渲染组件外部更改,恕不通知做出反应
  3. $('#target').destroy()被调用时,#target节点被从DOM中删除而不通知React
  4. 因此,当您在componentDidUpdate中调用$('#target').init()时,您无法找到#target因为反应。在#target没有检测到任何变化,由于该阵营不会选择重新渲染这个事实#target不会再生。

所以一两件事你可以做的是更新componentWillReceiveProps状态(in condition check),注意data-updated领域,这将确保阵营检测为this.state.content的状态变化,因此将重新呈现组件,您将在componentDidUpdate

componentWillReceiveProps(nextProps) { 
    if (condition) { 
    this.target.destroy(); // this remove even the DOM node 
    this.state.content = `<div id="target" data-updated="${Date.now()}">ciao!</div>`; 
    } 
} 

鉴于这一发现再次#target,我建议你看看refs的反应。

+0

你的答案有很多道理!稍后在工作中,我会试着让你知道。我知道裁判,但由于我已经“绕过”反应与jQuery在这casa我没有看到使用$选择器的问题..你认为是更好的使用裁判? – ciaoben

+0

使用方式没有太大的区别,但其中一个参数可能是$('#target')在DOM中找到所有内容(如果有其他'#target',也可能会影响性能)。相反,$(this.refs.target)使得这个jQuery选择器非常有效。 –

+0

谢谢...我试过你的解决方案,但没有工作......它没有任何意义......不能理解为什么不通过反应重新呈现,即使是与属性不同 – ciaoben

相关问题