开发者问题收集

点击时渲染反应组件

2017-02-10
5316

当我们单击“添加”链接时,我尝试呈现需求组件。 下面是我的主要组件的代码:

import React from 'react';
import ReactDOM from 'react-dom';
import { Hand } from './hand.js';
import { Need } from './need.js';

class App extends React.Component{
  constructor() {
    super();
    this.processHand = this.processHand.bind(this);
    this.addNeed = this.addNeed.bind(this);
    this.state = {
      inhandMoney : " ",
      renderNeed: false,
    }

  }

  processHand(e){
    e.preventDefault();
    const handMoneyReceived = this.handMoney.value;
    this.setState({
        inhandMoney: handMoneyReceived
    });     
  }

  addNeed(e){
    e.preventDefault();
    this.setState({
        renderNeed:true
    });
  }

  render(){ 

    const passNeed = (    
            <Need/>   
      );

    return(
        <div>
          <div className ="hand">
            <form onSubmit = {this.processHand}>
              <input type="text" ref= {ref => this.handMoney = ref}/>
              <input type="submit"/>
            </form>
            <Hand handMoney = {this.state.inhandMoney}/>
            <Need/>
          </div>
          {this.state.renderNeed ? passNeed : null}
          <a href="#" className="add" onClick = {this.addNeed}>add</a>
        </div>
      )
  }
}

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

下面是我的需求组件以防万一:

import React from 'react';

export class Need extends React.Component{
constructor() {
    super();
    this.processNeed = this.processNeed.bind(this);
    this.state ={
        why: " ",
        howMuch: 0
    }

}

processNeed(e){
    e.preventDefault();
    const why=this.why.value;
    const howMuch=this.howMuch.value;
    this.setState({
        why:why,
        howMuch:howMuch
    });
}

    render(){
        return(
          <div className ="need">
            <form onSubmit = {this.processNeed}>
              <input type="text" ref= {ref => this.why = ref}/>
              <input type="text" ref= {ref => this.howMuch = ref}/>
              <input type="submit"/>
            </form>
            <div>
                <h1>{this.state.why}</h1>
                <h1>{this.state.howMuch}</h1>
            </div>
          </div>            
        )
    }
}

我在第一次单击添加链接时实现了我想要实现的目标,即首先在没有任何条件的情况下呈现需求组件。当我单击“添加”时,需求组件再次呈现,但是当我第二次单击“添加”链接时,我没有看到任何变化。为什么会这样,我想每次单击“添加”链接时都呈现需求组件。

3个回答

以下是 针对您的问题的解决方案 。我尝试尽可能接近您的代码。

https://jsfiddle.net/birjubaba/t0yusos9/3/

@sean 给出的解释非常准确。

By default, calling setState will rerender component, no matter what valid arguments you pass to setState. So yes, it should be rerendering. It doesn't appear to be rerendering because, well, it's always displaying the same thing after the first click because renderNeed is always true after every click

React 维护虚拟 DOM,并且所有 DOM 操作都在此虚拟 DOM 中完成(在更新实际 DOM 之前)。添加 Need 组件是一种 DOM 操作。因此, 第一次 当我们单击“添加”时,它实际上会更新虚拟 DOM 以添加新的 Need 。现在,react diff 算法起作用了,它会更新实际的 DOM。因此, Need 组件显示在 UI 中。DOM 将如下所示:

div 
 |- div (class=hand)
      |-form
        |-input (type=text) 
        |-input (type=submit)
      |- Hand
      |- Need
 |-Need (added by clicking on add anchor tag)
 |-a (class=add)

下次单击“添加”时,this.state.renderNeed 再次为 true,因此,React 将尝试在虚拟 DOM 中添加 Need 组件(由于以下代码)。

{this.state.renderNeed ? passNeed : null}
<a href="#" className="add" onClick = {this.addNeed}>add</a>

但在添加 Need 之前,React diff 算法将运行,它将看到虚拟(和实际)DOM 中已经存在一个 Need 组件,该组件与它尝试添加的组件完全相似。React 会认为两个 DOM 相同,并且 UI 中没有任何更新。

您对添加的要求如下所示:

div 
 |- div (class=hand)
      |-form
        |-input (type=text) 
        |-input (type=submit)
      |- Hand
      |- Need
 |-Need (added by clicking on add anchor tag)
 |-Need (added by clicking on add anchor tag)
 |-Need (added by clicking on add anchor tag)
 |-Need (added by clicking on add anchor tag)
 |-a (class=add)

这可以通过维护 Need 组件数组并在单击添加时渲染它们来实现。 React diff 算法将负责更新虚拟 DOM 和实际 DOM 的所有优化。

我鼓励您浏览以下两个精彩的网站,其中正确解释了 React diff 算法。

  1. 在 Google 中搜索“Reconciliation - React”,然后从搜索结果中打开 Facebook React 页面
  2. https://calendar.perfplanet.com/2013/diff/
Brijesh Pandey
2017-02-14

从您的解释中,我了解到您想要在每次单击 add 链接时添加 Need 组件。

由于您对 render() 方法的错误理解,您提供的代码无法按您希望的方式工作。每次您单击 add 链接时,您的 <Need /> 组件都会重新渲染,但每次重新渲染的只有一个 <Need /> 组件。如果您想在每次单击 add 链接时渲染新组件。您将需要使用一个包含所有 <Need /> 组件的数组。

为了实现相同目的,我创建了一个名为 needArray 的状态变量。每次单击 add 链接时,都会在此状态变量中添加一个新的 <Need /> 组件,并呈现相同的组件。

constructor(props) {
    super(props)
    this.state = {renderNeed: false, needArray: []}
    this.addNeed = this.addNeed.bind(this)
}

addNeed(e) {
    e.preventDefault();
    // any another better approach can be used to generate unique key. I've used Math.random() for demo only.
    this.setState({
        renderNeed: true, 
        needArray: [<Need key={Math.random()}/>, ...this.state.needArray]
     })
}

render() {
    return (
      <div>
        <a href="#" onClick = {this.addNeed}>add</a>
        {this.state.renderNeed ? this.state.needArray : null}
      </div>
    )
}

这是工作小提琴的链接。为简洁起见,我只添加了所需的代码。 JSFiddle

Hardik Modha
2017-02-14

尝试: <a href="#" className="add" onClick = {this.addNeed.bind(this)}>add</a>

john_omalley
2017-02-13