当我们点击"添加"时,我正在尝试渲染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>
)
}
}
我正在实现我想要在第一次点击添加链接时实现的目标,即首先需要组件在没有任何条件的情况下呈现。当我点击&#34;添加&#34; Need组件再次渲染,但是当我点击&#34;添加&#34;第二次链接,我没有看到任何变化。为什么会这样,我想在每次点击&#34时添加需要组件;添加&#34;链接。
答案 0 :(得分:3)
以下是解决您问题的解决方案。我试着尽可能地接近你的代码。
https://jsfiddle.net/birjubaba/t0yusos9/3/
@sean给出的解释是正确的。
默认情况下,调用setState将重新呈现组件,无论如何 传递给setState的有效参数。是的,它应该是 重新描绘。它似乎不会重新渲染,因为它是 第一次点击后总是显示相同的东西,因为 每次点击后,renderNeed始终为真
React维护一个虚拟DOM,所有DOM操作都在这个虚拟DOM中完成(在更新实际DOM之前)。添加Need
组件是DOM操作。所以,第一次当我们点击&#34;添加&#34;它实际上更新了虚拟DOM以添加新的Need
。现在反应差异算法工作,它更新实际的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)
下次&#34;添加&#34;单击,this.state.renderNeed再次为true,因此,React将尝试在虚拟DOM中添加Need组件(由于下面的代码)。
{this.state.renderNeed ? passNeed : null}
<a href="#" className="add" onClick = {this.addNeed}>add</a>
但是在添加Need
之前,React diff算法将会运行,它会看到Virtual(和实际)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的所有优化。
我建议您通过以下两个精彩的网站,其中正确解释了反应差异算法。
答案 1 :(得分:1)
尝试:
<a href="#" className="add" onClick = {this.addNeed.bind(this)}>add</a>
答案 2 :(得分:1)
如果您想继续呈现需求集合,您可能希望在您的州内存储可以跟踪您的需求的数组。
否则,基于此引用 -
首先,need组件在没有任何条件的情况下呈现。当我点击“添加”时,Need组件再次呈现,但是当我第二次单击“添加”链接时,我看不到任何更改。
您似乎希望根据 renderNeed 布尔
跟踪的更改进行渲染默认情况下,无论您传递给setState的有效参数是什么,调用setState都会重新呈现组件。所以是的,应该重新渲染。它似乎没有重新渲染,因为,它在第一次点击后始终显示相同的内容,因为每次点击后renderNeed始终为真
这是一个很好的资源:ReactJS - Does render get called any time "setState" is called?
作为一个人为的例子,如果你真的想“重新渲染”你的组件,你可以做一些微不足道的事情,比如为renderNeed创建一个切换
addNeed(e){
e.preventDefault();
this.setState((prevState, props) => ({
renderNeed: !prevState.renderNeed
});
}
不推荐你这样做,因为你的addNeed函数没有按照它的名字暗示......
也是一个小小的小提示,以证明它正在重新渲染
https://jsfiddle.net/jwm6k66c/2131/
希望这有帮助。
答案 3 :(得分:1)
根据您的解释,我知道您每次点击Need
链接时都要添加add
组件。
由于您对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
答案 4 :(得分:0)
{this.state.renderNeed ? passNeed : null}
替换为
{this.state.renderNeed && <Need/> }
答案 5 :(得分:0)
1)实现这一目标的一种方法是:
<?php
$Pages = array(
'clothes' => 'Clothes',
'something' => 'Something'
);
$path = $_SERVER["PHP_SELF"];
$parts = explode('/',$path);
if (count($parts) < 2)
{
echo("home");
}
else
{
echo ("<a href=\"/\">Home</a> » ");
for ($i = 1; $i < count($parts); $i++)
{
if (!strstr($parts[$i],"."))
{
echo("<a href=\"");
for ($j = 0; $j <= $i; $j++) {echo $parts[$j]."/";};
echo("\">". str_replace('-', ' ', $Pages[$parts[$i]])."</a> » ");
}
else
{
$str = $parts[$i];
$pos = strrpos($str,".");
$parts[$i] = substr($str, 0, $pos);
echo str_replace('-', ' ', $Pages[$parts[$i]]);
};
};
};
?>
在渲染中,您可以添加以下密钥:
addNeed(e){
e.preventDefault();
this.setState({
needKey: Math.random()
});
}
2)另一种方式是:
<Need key={this.state.needKey} />
3)另外,可以使用forceUpdate完成。但是,通常不建议这样做:
addNeed(e){
e.preventDefault();
this.setState(this.state);
}
答案 6 :(得分:0)
我会创建一个带有空数组的初始状态键,每次单击“添加”时,您将增加数组的大小,然后您将数组映射到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>
}