【React】react input输入的时候输入一次就失去焦点,需要再次点击才能输入一次

如题,每次点击input的时候才能输入一次

查看了代码,原因应该是当我每次输入触发onChange的时候DOM重绘,但是根源并不清楚到底是什么,望指教;

因为是第一次用react,所以有什么问题大家也可以提出来,让我改进一下,谢谢!

代码如下
【React】react input输入的时候输入一次就失去焦点,需要再次点击才能输入一次

class Goods extends Component {

    constructor() {

super();

this.state = {

id: '',

name: '',

orderBy_id: 3,// 排序

isFilter: false,

type: '',//类型

page_num: 1, // 页码

min_price: '', // 最低价

max_price: '', // 最高价

screen_id: '', // 筛选选择类型

str: ''

};

this.changeSort = this.changeSort.bind(this);

this.changeProd = this.changeProd.bind(this);

this.selectedAttr = this.selectedAttr.bind(this);

this.resetAttr = this.resetAttr.bind(this);

this.selectedFilter = this.selectedFilter.bind(this);

this.changePrice = this.changePrice.bind(this);

this.closeModal = this.closeModal.bind(this);

}

changePrice(event) {

const target = event.target;

if(target.name === 'min_price') {

this.setState({

min_price: event.target.value

})

}else {

this.setState({

max_price: event.target.value

})

}

}

render() {

const {data} = this.props;

const SelectWrapper = () => {

return (

<TopWrapper>

<TopItem className={(this.state.orderBy_id === 3 && !this.state.isFilter) ? 'selected' : ''}

onClick={(e) => this.changeSort(e, 'other', 3)}>

<span className='text'>综合</span>

</TopItem>

<TopItem className={(this.state.orderBy_id === 5 && !this.state.isFilter) ? 'selected' : ''}

onClick={(e) => this.changeSort(e, 'other', 5)}>

<span className='text'>销量</span>

</TopItem>

<TopItem

className={((this.state.orderBy_id === 2 || this.state.orderBy_id === 1) && !this.state.isFilter) ? 'selected' : ''}

onClick={(e) => this.changeSort(e, 'price')}>

<span className='text'>价格</span>

<span className='icon'>

<i className={`iconfont icon-shangjiantou ${this.state.orderBy_id === 2 ? 'selected' : ''}`}></i>

<br/>

<i className={`iconfont icon-xiajiantou ${this.state.orderBy_id === 1 ? 'selected' : ''}`}></i>

</span>

</TopItem>

<TopItem className={this.state.isFilter ? 'selected' : ''}

onClick={(e) => this.changeSort(e, 'shaixuan')}>

<span className='text'>筛选</span>

<span className='icon'>

<i className='iconfont'></i>

<br/>

<i className={`iconfont icon-xiajiantou ${this.state.isFilter ? 'selected' : ''}`}></i>

</span>

</TopItem>

</TopWrapper>

)

};

const ProductContainers = () => {

let isSelf = (type) => {

if(type === '1') {

return (

<span>自营</span>

)

}

return null;

};

if(!data.length){

return null

}

return (

<ProductWrapper>{

data.map((item, index) => {

return (

<ProductItem key={index}>

<div className='img'>

<img src={item.image} alt=""/>

</div>

<p className='name'>

{

isSelf(item.support_type)

}

{item.name}

</p>

<p className='price'>¥

<span>

{(item.price).toFixed(2)}

</span>

</p>

</ProductItem>

)

})

}

</ProductWrapper>

)

};

const FilterContainer = () => {

const {isFilter, screen_id, min_price, max_price} = this.state;

const {options} = this.props;

if(isFilter) {

return (

<FilterWrapper>

<div className='content'>

<p className='title'>聚鲨服务</p>

<ul>

{

options.map((item, index) => {

if(screen_id.indexOf(item.id) > -1) {

return (

<li key={index} onClick={() => {this.selectedAttr(item.id)}} className='screen-select'>{item.name}

<img className='selected' src='http://wp.ghs.net/static/img/selectBg.png' alt=""/>

</li>

)

}else {

return (

<li key={index} onClick={() => {this.selectedAttr(item.id)}}>{item.name}</li>

)

}

})

}

</ul>

<p className='title'>价格区间</p>

<p className='price-range'>

<input type="text" name='min_price' placeholder='最低价' onChange={this.changePrice} value={min_price} />

<span>-</span>

<input type="text" name='max_price' placeholder='最高价' onChange={this.changePrice} value={max_price}/>

</p>

<div className='buttons'>

<p className='reset' onClick={this.resetAttr}>重置条件</p>

<p className='sure' onClick={this.selectedFilter}>确定</p>

</div>

</div>

<div className='model' onClick={this.closeModal}></div>

</FilterWrapper>

)

}

return null

};

return (

<Wrapper>

<SelectWrapper/>

<FilterContainer />

<ProductContainers/>

</Wrapper>

)

}

}

回答

应该是在循环中的 key 值使用了 index 的缘故吧。
由于 React 中的 diff 算法需要通过 key 值判断前后的虚拟 dom 是否发生了改变,加上 index 的值会动态改变的缘故,所以会导致 dom 重绘。
之前,我在循环中产生了包含 inputdom 结构,并使用了时间戳作为 key 值出现了同样的情况。

任何情况下建议给 key 一个固定唯一的值。

I hope this will help you.

不要在你的render中
return的时候有分支判断。

比如你的if(isFilter). 这是一种不好的实践,并且很容易有各种问题,包括你的这个问题。

你现在相当于在render里又定义了3个子组件
把render里的组件<SelectWrapper/> <FilterContainer /> <ProductContainers/>
拿到外面去,或者把他们写成一个方法放Goods里

import React from 'react';

import {render} from 'react-dom';

const mountPoint = document.createElement('div');

mountPoint.setAttribute('id', 'root');

document.body.appendChild(mountPoint);

class Goods extends React.Component {

constructor() {

super();

this.state = {

id: '',

name: '',

orderBy_id: 3,// 排序

isFilter: false,

type: '',//类型

page_num: 1, // 页码

min_price: '', // 最低价

max_price: '', // 最高价

screen_id: '', // 筛选选择类型

str: ''

};

this.changePrice = this.changePrice.bind(this);

}

changePrice(event) {

const target = event.target;

console.log(event.target.value)

if(target.name === 'min_price') {

this.setState({

min_price: event.target.value

})

}else {

this.setState({

max_price: event.target.value

})

}

}

filterContainer() {

const {isFilter, screen_id, min_price, max_price} = this.state;

return (

<div>

<div className='content'>

<p className='title'>聚鲨服务</p>

<p className='title'>价格区间</p>

<p className='price-range'>

<input type="text" name='min_price' placeholder='最低价' onChange={this.changePrice} value={min_price} />

<span>-</span>

<input type="text" name='max_price' placeholder='最高价' onChange={this.changePrice} value={max_price}/>

</p>

</div>

</div>

)

};

render() {

return (

<div>

{this.filterContainer()}

<p>min_price:{this.state.min_price}</p>

<p>max_price:{this.state.max_price}</p>

</div>

)

}

}

render(

<Goods />,

mountPoint

);

请问楼主解决这个问题了么 我今天也遇到了

这个原因是使用了高阶组件的原因,至于原因具体还不清楚,应该是修改状态的时候,重新执行render()方法,而你的输入框是写在高阶组件里面的,所以会导致重新执行你的高阶组件的那个方法,去重新渲染你的整个高阶组件,应该是react,diff算法的一个bug吧!

以上是 【React】react input输入的时候输入一次就失去焦点,需要再次点击才能输入一次 的全部内容, 来源链接: utcz.com/a/72244.html

回到顶部