React js:与其他元素相比,输入元素的呈现方式不同 [英] React js: Input element renders differently compared to other elements

查看:55
本文介绍了React js:与其他元素相比,输入元素的呈现方式不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了一个简单的应用程序(在 react js 中),它有两个列表,您可以向该列表添加元素.一个是输入元素列表,另一个是跨度列表.

添加新元素后,span 列表呈现完美,但输入列表呈现不同.

这就是我的 React 类的样子

var App = React.createClass({getInitialState: 函数(){返回 {'应用程序': {'数据':this.props.data,'data2': this.props.data2}};},点击:函数(){var dat = this.state.app.data;var val = this.refs.input.getDOMNode().value;dat.splice(0, 0, val);var dat2 = this.state.app.data2;dat2.splice(0, 0, val);this.setState({'app': {'数据':数据,'数据2':数据2}});},渲染元素:函数(i){返回(<输入默认值={i}/>);},renderElement2: 函数(i){返回(<span>{i}</span>);},渲染:函数(){var self = this;返回(<div><input type="text" ref="input" placeholder="输入一个值"/><input type="button" value="Add value" onClick={this.onclick}/><div className="col2">{this.state.app.data.map(function(page, i){返回(<div key={i}>{self.renderElement(page)}</div>);})}

<div className="col2">{this.state.app.data2.map(function(page, i){返回(<div key={i}>{self.renderElement2(page)}</div>);})}

);}});

这是应用程序的呈现方式

var data = [1,2,3];var data2 = [1,2,3];React.render(<App data={data} data2={data2}/>, document.getElementById("main"));

这是演示

我的测试用例:我添加 55 并希望结果如下所示5512355123但我得到123355123

我在这里遗漏了一些基本的东西吗?

解决方案

第一次渲染看起来(大致)如下:

<div key={0}><input defaultValue="1"/></div><div key={1}><input defaultValue="2"/></div><div key={2}><input defaultValue="3"/></div>

<div><div key={0}><span>1</span></div><div key={1}><span>2</span></div><div key={2}><span>3</span></div>

很酷,没问题.然后假设我将foo"放入框中并单击添加值".通过在第一项之前插入它来更新状态(旁注:splice(0,0,x) 是 unshift(x)),然后渲染它:

<div key={0}><input defaultValue="foo"/></div><div key={1}><input defaultValue="1"/></div><div key={2}><input defaultValue="2"/></div><div key={3}><input defaultValue="3"/></div>

<div><div key={0}><span>foo</span></div><div key={1}><span>1</span></div><div key={2}><span>2</span></div><div key={3}><span>3</span></div>

现在是时候让 React 接受这两个,并找出发生了什么变化.为此,它会比较组件(此处为 div、span 或输入)和键.

从 span 部分开始,它看到所有标签都相同,但在末尾有一个它以前没有见过的新键.它还看到div[0] spandiv[1] spandiv[2] span 的值都发生了变化.它在末尾插入带有文本 3 的 new 元素,并更新其他跨度.效率低下,但有效.

现在对于输入......它做的事情大致相同.前三个输入的键和标签是相同的,它告诉每个输入它们正在更新,它们检查它们是否有值道具,如果没有,请拒绝做任何事情.

它看到最后有一个输入.它位于 div[3] input 处,默认值为3".React 插入新输入,将值设置为 3,更新完成.

随着你继续,上面的过程是一样的,它继续更新span,每次插入一个新的div spandiv input.

这里的主要问题,除了我认为不应该使用的 defaultValue 之外,是键是颠倒的!项目在开头插入,因此键应该下降,而不是上升.这可以通过使用项目的长度并从中减去索引来解决.如果长度为 4,则键为 4、3、2、1.

this.state.app.data.map(function(page, i, items){返回(<div key={items.length - i}>{self.renderElement(page)}</div>);})

React 然后说哦,在开始有一个新项目,我应该在那里插入一个节点",每个人都很高兴.结束.

I made a simple application (in react js) that has two lists and you can add elements to that list. One is a list of input elements and other is list of spans.

Upon adding new element, the list of span renders perfectly but the list of inputs renders differently.

This is how my react class looks like

var App = React.createClass({
  getInitialState: function(){
    return {
      'app': {
        'data': this.props.data,
        'data2': this.props.data2
      }
    };
  },
  onclick: function(){
    var dat = this.state.app.data;
    var val = this.refs.input.getDOMNode().value;

    dat.splice(0, 0, val);

    var dat2 = this.state.app.data2;
    dat2.splice(0, 0, val);

    this.setState({'app': {
      'data': dat,
      'data2': dat2
    }});

  },
  renderElement: function(i){
    return(
      <input defaultValue={i} />
    );
  },
  renderElement2: function(i){
    return(
      <span>{i}</span>
    );
  },
  render: function(){
    var self = this;
    return(
      <div>
        <input type="text" ref="input" placeholder="Enter a value"/>
        <input type="button" value="Add value" onClick={this.onclick} />
        <div className="col2">
          {this.state.app.data.map(function(page, i){
              return(
                <div key={i}>{self.renderElement(page)}</div>
              );
          })}
        </div>
        <div className="col2">
          {this.state.app.data2.map(function(page, i){
              return(
                <div key={i}>{self.renderElement2(page)}</div>
              );
          })}
        </div>
      </div>
    );
  }
});

This is how the App is rendered

var data =  [1,2,3];
var data2 =  [1,2,3];

React.render(<App data={data} data2={data2}/>, document.getElementById("main"));

Here is the DEMO

My test case:
I add 55 and expect the results to look like this 
55
1
2
3
55
1
2
3

But I get
1
2
3
3
55
1
2
3

Am I missing something basic here ?

解决方案

First render looks (roughly) like this:

<div>
 <div key={0}><input defaultValue="1" /></div>
 <div key={1}><input defaultValue="2" /></div>
 <div key={2}><input defaultValue="3" /></div>
</div>
<div>
 <div key={0}><span>1</span></div>
 <div key={1}><span>2</span></div>
 <div key={2}><span>3</span></div>
</div>

Cool, no problems. Then let's say I put 'foo' in the box and click Add Value. The state updates by inserting it before the first item (side note: splice(0,0,x) is unshift(x)), you then render this:

<div>
 <div key={0}><input defaultValue="foo" /></div>
 <div key={1}><input defaultValue="1" /></div>
 <div key={2}><input defaultValue="2" /></div>
 <div key={3}><input defaultValue="3" /></div>
</div>
<div>
 <div key={0}><span>foo</span></div>
 <div key={1}><span>1</span></div>
 <div key={2}><span>2</span></div>
 <div key={3}><span>3</span></div>
</div>

Now it's time for React to take these two, and figure out what changed. To do this it compares the component (div, span, or input here), and the keys.

Starting with the span section, it sees that all the tags are the same, but there's a new key it hasn't seen before at the end. It also sees that the value of div[0] span, div[1] span, and div[2] span have all changed. It inserts the new elements with the text 3 at the end, and updates the other spans. Inefficient, but it works.

Now for the inputs... it does roughly the same thing. The keys and tags for the first three inputs are the same, it tells each of the inputs that they're updating, they check if they have a value prop, and if not, kindly deny to do anything.

It sees that there's a new input at the end. It is at div[3] input and has a defaultValue of "3". React inserts the new input, sets the value to 3, and the update is complete.

As you continue, the above procedure is the same, and it continues updating the spans, and inserting a new div span and div input each time.

The main problem here, aside from defaultValue which I don't think should ever be used, is the keys are upside down! Items are being inserted at the beginning, so keys should descend, not ascend. This can be fixed by using the length of the items and subtracting the index from that. If length is 4, the keys will be 4, 3, 2, 1.

this.state.app.data.map(function(page, i, items){
  return(
    <div key={items.length - i}>{self.renderElement(page)}</div>
  );
})

React then says 'oh, there's a new item at the beginning, I should just insert a node there', and everyone's happy. The end.

这篇关于React js:与其他元素相比,输入元素的呈现方式不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆