击键后,reactjs输入元素失去焦点

时间:2017-10-30 02:00:59

标签: javascript reactjs

所以我使用哈希来存储动态创建的输入值行的值,并且在输入一个字符后我将注意力集中在我正在修改的输入上。我认为解决这个问题的方法可能是使用refs重新关注最后输入的输入,但我无法使其工作,因为我无法弄清楚如何指定哪个元素是最后一个改变。关于如何解决这个问题的建议表示赞赏。

下面的代码动态创建输入框,并根据unitPriceValueHash查找其值。每个变体都有一个id,id用作哈希的键。

我创建了一个codepen来尝试重新创建问题,但我面临的问题并没有出现在代码笔中。在我的实际应用程序中,我在输入框中按1,例如光标不再在输入框上。

https://codepen.io/ByteSize/pen/oogLpE?editors=1011

codepen和我的代码之间的唯一区别似乎是输入嵌套在表中。

Inputs nested in table

  CreateItem(variant) {
    const unitPriceValueHash = this.props.unitPriceValueHash
    return { 
      variant_title: variant.variant_title,
      variant_price: variant.variant_price,
      unit_cost: <TextField 
                  type="number"
                  onChange={(event) => this.handleUnitPriceChange(variant.id, event)}
                  key={variant.id}
                  value={unitPriceValueHash[variant.id] || ''}
                 />
    };
  }

以下是修改哈希值的状态更改

  handleUnitPriceChange (id, event) {
    const unitPriceValueHash = this.state.unitPriceValueHash
    unitPriceValueHash[id] = event
    console.log(unitPriceValueHash)
    this.setState({unitPriceValueHash: unitPriceValueHash});
    //this.updateVariantUnitCost(id, event);
  }

2 个答案:

答案 0 :(得分:1)

您分享的代码存在一些问题。

  • 不要使用内联函数。每个渲染,再次创建函数,这意味着当react比较道具时,它看起来像函数不同(每次都是一个新的/不同的函数!)并且反应将重新渲染。
  • 不要修改状态中存在的任何对象,而是创建新对象。如果修改状态中存在的对象,则基本上是说您不希望渲染具有一致性和可重现性。

我重新发布了原始代码,其中突出显示了问题

CreateItem(variant) {
  const unitPriceValueHash = this.props.unitPriceValueHash
  return {
    variant_title: variant.variant_title,
    variant_price: variant.variant_price,
    unit_cost: <TextField
      type="number"
      onChange={(event) => this.handleUnitPriceChange(variant.id, event)}
      // ^^^^ - inline functions cause react to re-render every time, instead - create a component
      key={variant.id}
      value={unitPriceValueHash[variant.id] || ''}
    />
  };
}

handleUnitPriceChange(id, event) {
  const unitPriceValueHash = this.state.unitPriceValueHash
  unitPriceValueHash[id] = event
  // ^^^^ - please, please - don't do this. You can't mutate the state like this.

  // instead, do the following to create a new modified object without modifying the object in the state
  const unitPriceValueHash = Object.assign({}, this.state.unitPriceValueHash, { id: event });
  this.setState({ unitPriceValueHash: unitPriceValueHash });
}

关于内联函数,通常建议为此创建一个新组件,将该值作为prop。这可能是这样的:

class UnitCost extends PureComponent {
  static propTypes = {
    variantId: PropTypes.number,
    variantValue: PropTypes.object,
    onUnitPriceChange: PropTypes.func,
  }
  handleUnitPriceChange(e) {
    this.props.onUnitPriceChange(this.props.variantId, e)
  }
  render() {
    return (
      <TextField
        type="number"
        onChange={this.handleUnitPriceChange}
        value={this.props.variantValue || ''}
      />
    );
  }
}

CreateItem(variant) {
  const unitPriceValueHash = this.props.unitPriceValueHash
  return {
    variant_title: variant.variant_title,
    variant_price: variant.variant_price,
    unit_cost: (
      <UnitCost
        key={variant.id}
        variantId={variant.id}
        variantValue={unitPriceValueHash[variant.id]}
        onUnitPriceChange={this.handleUnitPriceChange}
      />
    ),
  };
}

关于你对焦点的关注,反应通常不会在重新渲染时失去你的对象焦点,所以不要 永远 重新聚焦对象之后因此的更新。

唯一的反应将失去焦点,如果它完全丢弃当前的DOM树并从头开始。如果它认为父对象已被替换而不是被修改,它将执行此操作。这可能是因为缺少key道具或key道具已发生变化。

您尚未发布足够的代码供我们进一步调查。如果您需要更多帮助,您应该构建一个我们可以运行和测试的最小可重复示例。

答案 1 :(得分:0)

这个问题的解决方案让我使用中间状态来存储更改时输入字段的值,以及onBlur上的提交AJAX请求

class TextFieldWrapper extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: this.props.variantValue[this.props.variantId] || '',
    }
    this.handleUnitPriceChange = this.handleUnitPriceChange.bind(this)
    this.updateValue = this.updateValue.bind(this)
  }
  updateValue(value){
    this.setState({
      value: value,
    });
  }
  handleUnitPriceChange() {
    this.props.onUnitPriceChange(this.props.variantId, this.state.value);
  }
  render(){
    return (
      <TextField
        type="number"
        id={this.props.variantId}
        key={this.props.variantId}
        onChange={this.updateValue}
        onBlur={this.handleUnitPriceChange}
        value={this.state.value}
      />
    );
  }
}