单击时渲染反应组件
rendering react components on click
当我们单击 "add" link 时,我正在尝试渲染 Need 组件。
下面是我的主要组件代码:
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>
)
}
}
我在第一次点击添加 link 时实现了我想要实现的目标,即首先当我点击 [=18= 时,需要的组件在没有任何 condition.and 的情况下呈现] Need 组件再次呈现,但是当我第二次单击 "add" link 时,我没有看到任何变化。为什么会这样,我想在每次点击 "add" link.
时渲染 Need 组件
{this.state.renderNeed ? passNeed : null}
替换为
{this.state.renderNeed && <Need/> }
尝试:
<a href="#" className="add" onClick = {this.addNeed.bind(this)}>add</a>
1) 实现此目的的一种方法是:
addNeed(e){
e.preventDefault();
this.setState({
needKey: Math.random()
});
}
并且在你的渲染中你可以添加这个键:
<Need key={this.state.needKey} />
2) 另一种方式是:
addNeed(e){
e.preventDefault();
this.setState(this.state);
}
3) 另外,可以使用forceUpdate 来完成。不过一般不推荐:
addNeed(e) {
e.preventDefault();
this.forceUpdate()
}
我会创建一个带有空数组的初始状态键,每次单击 'add' 都会增加数组的大小,然后将数组映射到 render()。像这样:
constructor() {
super();
this.processHand = this.processHand.bind(this);
this.addNeed = this.addNeed.bind(this);
this.state = {
inhandMoney : " ",
fields: [],
}
}
addNeed(e){
e.preventDefault();
this.setState({
fileds: this.state.fields.push(1),
});
}
render() {
<div>
<div className="hand">
<form onSubmit={this.processHand}>
<input type="text" ref={ref => this.handMoney = ref}/>
<input type="submit"/>
</form>
<Need/>
</div>
{this.state.fields.map(i => <Need key={i} />)}
<a href="#" className="add" onClick={this.addNeed}>add</a>
</div>
}
如果您想继续呈现需求集合,您可能希望在您的状态中存储一个数组,以跟踪您的需求。
否则,基于此引用-
at first the need component gets rendered without any condition.and when i click on "add" the Need component is rendered again but when i click the "add" link for the second time, i don't see any changes.
您似乎想根据 renderNeed 布尔值
跟踪的更改进行渲染
默认情况下,无论您传递给 setState 的有效参数是什么,调用 setState 都会重新呈现组件。所以是的,它应该重新渲染。它似乎没有重新渲染,因为,好吧,它在第一次点击后总是显示相同的东西,因为每次点击后 renderNeed 总是正确的
这是一个很好的资源:ReactJS - Does render get called any time "setState" is called?
作为一个人为的例子,如果你真的想要 "rerender" 你的组件,你可以做一些微不足道的事情,比如为 renderNeed
创建一个切换
addNeed(e){
e.preventDefault();
this.setState((prevState, props) => ({
renderNeed: !prevState.renderNeed
});
}
不建议您这样做,因为您的 addNeed 函数没有按其名称建议的方式执行...
也有点fiddle证明是re-rendering
https://jsfiddle.net/jwm6k66c/2131/
希望对您有所帮助。
根据您的解释,我了解到您想在每次单击 add
link 时添加 Need
组件。
由于您对 render()
方法的错误理解,您提供的代码无法按照您希望的方式工作。每次单击 add
link 时,您的 <Need />
组件将 re-render 但每次只有一个 <Need />
组件 re-render。如果您想在每次单击 add
link 时渲染新组件。您将需要使用一个包含所有 <Need />
组件的数组。
为了达到同样的目的,我创建了一个名为 needArray
的状态变量。每次点击 add
link,都会在这个状态变量中添加一个新的 <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>
)
}
这里是工作 fiddle 的 link。为简洁起见,我只添加了需要的代码。 JSFiddle
以下是针对您的问题的解决方案fiddle。我尽量接近你的代码。
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 操作。因此,第一次 当我们单击 "add" 时,它实际上会更新虚拟 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)
下次单击 "add" 时,this.state.renderNeed 再次为真,因此,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 的所有优化。
我鼓励您浏览以下两个很棒的站点,其中正确解释了反应差异算法。
- 在 Google 中搜索 "Reconciliation - React" 并从搜索结果中打开 facebook React 页面
- https://calendar.perfplanet.com/2013/diff/
当我们单击 "add" link 时,我正在尝试渲染 Need 组件。 下面是我的主要组件代码:
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>
)
}
}
我在第一次点击添加 link 时实现了我想要实现的目标,即首先当我点击 [=18= 时,需要的组件在没有任何 condition.and 的情况下呈现] Need 组件再次呈现,但是当我第二次单击 "add" link 时,我没有看到任何变化。为什么会这样,我想在每次点击 "add" link.
时渲染 Need 组件 {this.state.renderNeed ? passNeed : null}
替换为
{this.state.renderNeed && <Need/> }
尝试:
<a href="#" className="add" onClick = {this.addNeed.bind(this)}>add</a>
1) 实现此目的的一种方法是:
addNeed(e){
e.preventDefault();
this.setState({
needKey: Math.random()
});
}
并且在你的渲染中你可以添加这个键:
<Need key={this.state.needKey} />
2) 另一种方式是:
addNeed(e){
e.preventDefault();
this.setState(this.state);
}
3) 另外,可以使用forceUpdate 来完成。不过一般不推荐:
addNeed(e) {
e.preventDefault();
this.forceUpdate()
}
我会创建一个带有空数组的初始状态键,每次单击 'add' 都会增加数组的大小,然后将数组映射到 render()。像这样:
constructor() {
super();
this.processHand = this.processHand.bind(this);
this.addNeed = this.addNeed.bind(this);
this.state = {
inhandMoney : " ",
fields: [],
}
}
addNeed(e){
e.preventDefault();
this.setState({
fileds: this.state.fields.push(1),
});
}
render() {
<div>
<div className="hand">
<form onSubmit={this.processHand}>
<input type="text" ref={ref => this.handMoney = ref}/>
<input type="submit"/>
</form>
<Need/>
</div>
{this.state.fields.map(i => <Need key={i} />)}
<a href="#" className="add" onClick={this.addNeed}>add</a>
</div>
}
如果您想继续呈现需求集合,您可能希望在您的状态中存储一个数组,以跟踪您的需求。
否则,基于此引用-
at first the need component gets rendered without any condition.and when i click on "add" the Need component is rendered again but when i click the "add" link for the second time, i don't see any changes.
您似乎想根据 renderNeed 布尔值
跟踪的更改进行渲染默认情况下,无论您传递给 setState 的有效参数是什么,调用 setState 都会重新呈现组件。所以是的,它应该重新渲染。它似乎没有重新渲染,因为,好吧,它在第一次点击后总是显示相同的东西,因为每次点击后 renderNeed 总是正确的
这是一个很好的资源:ReactJS - Does render get called any time "setState" is called?
作为一个人为的例子,如果你真的想要 "rerender" 你的组件,你可以做一些微不足道的事情,比如为 renderNeed
创建一个切换 addNeed(e){
e.preventDefault();
this.setState((prevState, props) => ({
renderNeed: !prevState.renderNeed
});
}
不建议您这样做,因为您的 addNeed 函数没有按其名称建议的方式执行...
也有点fiddle证明是re-rendering
https://jsfiddle.net/jwm6k66c/2131/
希望对您有所帮助。
根据您的解释,我了解到您想在每次单击 add
link 时添加 Need
组件。
由于您对 render()
方法的错误理解,您提供的代码无法按照您希望的方式工作。每次单击 add
link 时,您的 <Need />
组件将 re-render 但每次只有一个 <Need />
组件 re-render。如果您想在每次单击 add
link 时渲染新组件。您将需要使用一个包含所有 <Need />
组件的数组。
为了达到同样的目的,我创建了一个名为 needArray
的状态变量。每次点击 add
link,都会在这个状态变量中添加一个新的 <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>
)
}
这里是工作 fiddle 的 link。为简洁起见,我只添加了需要的代码。 JSFiddle
以下是针对您的问题的解决方案fiddle。我尽量接近你的代码。
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 操作。因此,第一次 当我们单击 "add" 时,它实际上会更新虚拟 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)
下次单击 "add" 时,this.state.renderNeed 再次为真,因此,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 的所有优化。
我鼓励您浏览以下两个很棒的站点,其中正确解释了反应差异算法。
- 在 Google 中搜索 "Reconciliation - React" 并从搜索结果中打开 facebook React 页面
- https://calendar.perfplanet.com/2013/diff/