在更新状态下反应失去对输入的关注。一次只能更新一个字符

时间:2019-11-05 18:55:10

标签: javascript reactjs

我尝试更新输入的状态,但是输入的重点不再是每次击键。所以我一次只能输入一个字符。我想这与组件的重新渲染有关吗?

状态会更新,但一次只能更新一个字符。

import React, { useState } from 'react'

const InitialState = [
  {
    Id: 1,
    Server: 'server-1',
    IpAdress: '151.222.33.2'
  },
  {
    Id: 2,
    Server: 'server-2',
    IpAdress: '152.332.22.1'
  }
]

const Grid = props => {
  const [data, setData] = useState(InitialState)

  const getKeys = () => {
    return Object.keys(data[0])
  }

  const renderHeader = () => {
    return (
      <tr>
        {getKeys().map(key => {
          return <th>{key}</th>
        })}
      </tr>
    )
  }

  const getRowsData = () => {
    var items = data
    var keys = getKeys()
    return items.map((row, index) => {
      return (
        <tr key={index} data-row={index}>
          <RenderRow key={index} data={row} keys={keys} rowIndex={index} />
        </tr>
      )
    })
  }

  const RenderRow = props => {
    console.log()
    return props.keys.map((key, index) => {
      return (
        <td>
          <input
            data-index={index}
            data-key={key}
            data-row={props.rowIndex}
            value={data[props.rowIndex][key]}
            type='text'
            onChange={event => updateData(props, event, props.rowIndex, key)}
          />
        </td>
      )
    })
  }

  const updateData = (props, event, rowIndex, key) => {
    let update = [...data]
    update[rowIndex][key] = event.target.value
    setData(update)
  }

  return (
    <table>
      {renderHeader()}
      {getRowsData()}
    </table>
  )
}

export default Grid

有人知道我的代码有什么问题吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

更改renderRow定义为组件的方式,将其定义为render函数,然后它将解决您的问题。在https://codesandbox.io/s/kind-snyder-pjqqk

处查看我的codesanbox
const renderRow = props => {
    return props.keys.map((key, index) => {
      return (
        <td>
          <input
            data-index={index}
            data-key={key}
            data-row={props.rowIndex}
            value={data[props.rowIndex][key]}
            type="text"
            onChange={event => updateData(props, event, props.rowIndex, key)}
          />
        </td>
      );
    });
  };

  const getRowsData = () => {
    var items = data;
    var keys = getKeys();
    return items.map((row, index) => {
      return (
        <tr key={index} data-row={index}>
          {renderRow({ data: row, keys, rowIndex: index })}
        </tr>
      );
    });
  };

如果您想进一步了解原因,可以参考问题Why does React discard the entire DOM subtree and recreate it from scratch?

答案 1 :(得分:0)

每次In [33]: fruits = ["banana", "apple", "mango", "kiwi"] In [34]: add = ["peach"] In [35]: %timeit [v for v in itertools.zip_longest(fruits, add, fillvalue=add[0])] 859 ns ± 16.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) In [36]: %timeit list(itertools.chain.from_iterable(zip(fruits, itertools.repeat(*add)))) 992 ns ± 40.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) In [37]: %timeit list(itertools.chain(*itertools.product(fruits, add))) 1.05 µs ± 18 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) In [38]: %timeit [i for s in [[f, *add] for f in fruits] for i in s] 1.25 µs ± 73.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) In [39]: %timeit [fruits[i // 2] if i % 2 == 0 else "peach" for i in range(len(fruits) * 2)] 1.29 µs ± 12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 渲染时,您都在创建新的RenderRow组件。您应该在组件之外定义它。