【问题标题】:ReactDOM.render doesn't update component on props changeReactDOM.render 不会在道具更改时更新组件
【发布时间】:2020-06-17 08:32:49
【问题描述】:

我创建了一个非常小的应用程序来演示我的查询。

下面显示的代码具有使用 ReactDOM.render 将组件动态添加到 DOM 的功能,并且该组件带有一个名为 title 的道具,但是当我更新父组件的标题(在 state 中)时,DynamicComponent 不会更新.

import React from 'react';
import ReactDOM from 'react-dom';

const DynamicComponent = (props) => {
    return (
        <div style={{ 'border': '2px dotted green' }} >Dynamic Component : {props.title}</div>
    )
}

class App extends React.Component {
    state = {
        title: 'Iam Title'
    }

    addBlock = () => {
        return ReactDOM.render(<DynamicComponent title={this.state.title} />, document.getElementById('dynamiccomponents'))
    }

    render() {
        return (
            <div>
                <div>Value in state: <b>{this.state.title}</b></div>
                <p><b>&lt;DynamicComponent /&gt;</b> Added Initially</p>
                <DynamicComponent title={this.state.title} />
                <br />
                <p><b>&lt;DynamicComponent /&gt;</b> Added By ReactDOM.render will be shown below: </p>
                <div id="dynamiccomponents"></div>



                <button onClick={this.addBlock} >Click to Dynamic Component</button>
                <button onClick={() => this.setState({ title: `Update Title` })} >Update Title</button>
            </div>
        )
    }
}

ReactDOM.render(<App />, document.getElementById('root'));

第一个按钮用于添加 DynamicComponent,按预期工作正常。 第二个按钮用于更新状态中的标题,现在标题已更改但 DynamicComponent 仍然没有更新。

我是否遗漏了什么,我该如何解决这个问题,任何帮助将不胜感激

谢谢

【问题讨论】:

    标签: javascript reactjs react-dom


    【解决方案1】:

    这是因为当您调用addBlock 时,您只会将&lt;DynamicComponent title={this.state.title} /&gt; 渲染一次到&lt;div id="dynamiccomopnents"&gt;&lt;/div&gt;

    当您通过单击按钮更新title 的状态时,它会重新运行您的应用程序的render 函数,但this.addBlock 不会在您的render 函数中再次运行,因此您的标题不会得到更新。您可以通过再次单击调用this.addBlock 的按钮来验证这一点。它将使用更新的标题再次呈现您的组件。

    我建议你引入一些状态来有条件地渲染你的组件,而不是使用ReactDOM.render。这样,每次运行 render 方法时,您的组件都会重新渲染。这是一个例子:

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const DynamicComponent = (props) => {
      return (
        <div style={{ 'border': '2px dotted green' }} >Dynamic Component : {props.title}</div>
      )
    }
    
    class App extends React.Component {
      state = {
        title: 'Iam Title',
        showBlock: false,
      }
    
      addBlock = () => {
        // this method now sets `this.state.showBlock` to true
        this.setState({ showBlock: true });
      }
    
      renderBlock = () => {
        // return any component you want here, you can introduce some conditional
        // logic or even return nested elements, for example:
        return (
          <div>
            <p>Dynamic Component!</p>
            <DynamicComponent title={this.state.title} />
          </div>
        );
      }
    
      render() {
        return (
          <div>
            <div>Value in state: <b>{this.state.title}</b></div>
            <p><b>&lt;DynamicComponent /&gt;</b> Added Initially</p>
            <DynamicComponent title={this.state.title} />
            <br />
            <p><b>&lt;DynamicComponent /&gt;</b> Added By ReactDOM.render will be shown below: </p>
    
            {/* This will run `this.renderBlock` only if `this.state.showBlock` is true */}
            {this.state.showBlock && this.renderBlock()}
    
    
    
            <button onClick={this.addBlock} >Click to Dynamic Component</button>
            <button onClick={() => this.setState({ title: `Update Title` })} >Update Title</button>
          </div>
        )
      }
    }
    
    ReactDOM.render(<App />, document.getElementById('root'));
    

    【讨论】:

    • 感谢@khuyuh,但是 DynamicComponent 不会是上面任意数量的动态组件可以存在的单个组件,这应该只是为了演示问题。是将特定组件添加到 div 元素的任何方法,并且应该可以在状态更改时正常工作
    • 在这种情况下,我建议您创建一个函数,将您想要的任何组件呈现到该位置。我将在上面编辑我的答案,如果这能解决您的问题,请告诉我
    • 好的,我等你的答复
    • 查看编辑后的答案,我添加了一个名为renderBlock 的方法,它可以返回任何组件并将其渲染到该位置。
    • 不@khuyuh,这并不能解决我的问题,实际上我正在使用bevacqua.github.io/react-dragula 它是一个拖放插件,其中左侧字段将在放下时下降到右侧获取 el(由 dragula 事件提供)我使用 ReactDOM.render 插入我的反应组件
    【解决方案2】:

    您可以在状态更改后使用 LifeCycle 方法 componentDidUpdate() 重新渲染组件

        import React from "react";
    import ReactDOM from "react-dom";
    
    const DynamicComponent = props => {
      return (
        <div style={{ border: "2px dotted green" }}>
          Dynamic Component : {props.title}
        </div>
      );
    };
    
    class App extends React.Component {
      state = {
        title: "Iam Title"
      };
    
      addBlock = () => {
        return ReactDOM.render(
          <DynamicComponent title={this.state.title} />,
          document.getElementById("dynamiccomponents")
        );
      };
      componentDidUpdate() {
        return ReactDOM.render(
          <DynamicComponent title={this.state.title} />,
          document.getElementById("dynamiccomponents")
        );
      }
    
      render() {
        return (
          <div>
            <div>
              Value in state: <b>{this.state.title}</b>
            </div>
            <p>
              <b>&lt;DynamicComponent /&gt;</b> Added Initially
            </p>
            <DynamicComponent title={this.state.title} />
            <br />
            <p>
              <b>&lt;DynamicComponent /&gt;</b> Added By ReactDOM.render will be
              shown below:{" "}
            </p>
            <div id='dynamiccomponents'></div>
    
            <button onClick={this.addBlock}>Click to Dynamic Component</button>
            <button onClick={() => this.setState({ title: `Update Title` })}>
              Update Title
            </button>
          </div>
        );
      }
    }
    
    export default App;
    

    【讨论】:

    • 有没有其他方法不用重新渲染它,我的意思是如果我改变道具它应该反映组件的权利
    • 好吧,您可以拥有某种集中状态并在所有组件中使用它。参考:[stackoverflow.com/a/38904385/9871756]
    【解决方案3】:

    ReactDOM.render 只渲染一次元素。它创建了一个不同的树,它没有连接到你的第一棵树。也就是说,React 不会跟踪您可能曾经调用过的所有 ReactDOM.renders,并且不会使用用于创建它们的数据来更新它们

    如果您需要在 App 组件之外的 DOM 树中某处渲染元素,但又希望它与您的 App 组件连接(以便它对状态更改做出反应),请使用 ReactDOM.createPortal

    【讨论】:

      猜你喜欢
      • 2018-08-09
      • 2020-01-19
      • 1970-01-01
      • 2019-03-03
      • 2021-06-15
      • 2018-01-15
      • 1970-01-01
      • 1970-01-01
      • 2020-10-10
      相关资源
      最近更新 更多