Как мне автоматически сохранить несколько полей формы в React?

У меня есть onBlur в текстовых полях ввода, которые автоматически сохраняют запись; Структура данных - это один документ, который содержит массив элементов. Если я быстро изменю первый столбец элемента, а затем второй столбец, сохранение первого столбца вызовет обновление, которое перезагрузит оба поля ввода.

Как я могу предотвратить перезагрузку всей строки при первом сохранении, чтобы значения обоих столбцов были сохранены?

Вот фрагмент кода (я имитировал сохранение сервера с помощью setTimeout):

class Store {
  static doc = {title: "test title", items: [{id: 1, one: "aa", two: "bbb"}, {id: 2, one: "yyy", two: "zzz"}]};

  static getDocument() {
    return this.doc;
  }

  static saveDocument(doc) {
      this.doc = doc;
  }

  static updateItemInDocument(item, callback) {
      var foundIndex;
      let updatedEntry = this.doc.items.find( (s, index) => {
        foundIndex = index;
        return s.id === item.id;
      });

      this.doc.items[foundIndex] = item;
      setTimeout(() => { console.log("updated"); callback(); }, 1000);
  }
};

const Row = React.createClass({
  getInitialState() {
    return {item: this.props.item};  
  },

  update() {
    let document = Store.getDocument();

    let updatedEntry = document.items.find( (s) => {
            return s.id === this.props.item.id;
        } );

     this.setState({ item: updatedEntry});
  },

  handleEdit() {
    this.setState({item: {
        id: this.props.item.id,
        one: this.refs.one.value,
        two: this.refs.two.value
      }
    });  
  },

  handleSave() {
    Store.updateItemInDocument(this.state.item, this.update);
  },

  render() {
    let item = this.state.item;
    console.log(item);
    return  <tr> <p>Hello</p>
        <input ref="one" type="text" onChange={this.handleEdit} onBlur={this.handleSave} value={item.one} />
        <input ref="two" type="text" onChange={this.handleEdit} onBlur={this.handleSave} value={item.two} />
      </tr>;
  }
});

const App = React.createClass({
  render() {
    let rows = Store.getDocument().items.map( (item, i) => {
      return <Row key={i} item={item} />;
    });

    return <table>
      {rows}
      </table>;
  }
});

ReactDOM.render(
  <App />,
  document.getElementById("app")
);

У меня также есть код в виде кода: http://codepen.io/tommychheng/pen/zBNxeW?editors=1010


person tommy chheng    schedule 24.06.2016    source источник
comment
item всегда и имеет только свойства one и two? Или может item иметь больше или меньше этих свойств?   -  person Ashitaka    schedule 25.06.2016
comment
item имеет фиксированное количество свойств (всего одно и два) и полей ввода.   -  person tommy chheng    schedule 27.06.2016


Ответы (1)


Проблема связана с тем, что при выходе из поля ввода срабатывают обработчики onChange и onBlur.

Возможно, я неправильно понимаю ваш вариант использования, но вот как я могу исправить эту проблему:

const Row = React.createClass({
  getInitialState() {
    return { item: this.props.item };
  },

  handleSave() {
    let item = {
      id: this.state.item.id,
      one: this.refs.one.value,
      two: this.refs.two.value
    }
    Store.updateItemInDocument(item); // Is it really necessary to use the callback here?
  },

  render() {
    let item = this.state.item;
    return (
      <tr>
        <p>Hello</p>
        <input ref="one" type="text" onBlur={this.handleSave} defaultValue={item.one} />
        <input ref="two" type="text" onBlur={this.handleSave} defaultValue={item.two} />
      </tr>
    );
  }
});

Я перешел с использования обработчика onChange на с использованием значения по умолчанию.

person Ashitaka    schedule 27.06.2016
comment
Спасибо, Ашитака! я не знал о defaultValue. Это решает проблему, когда обновление перезаписывает значения после обновления. Моя проблема похожа на stackoverflow.com/questions/37946229/, где комментатор предлагает использовать defaultValue результаты в uncontrolled component, что является плохой практикой. Есть ли у вас мысли по поводу uncontrolled component? - person tommy chheng; 27.06.2016
comment
Я не думаю, что использование defaultValue - плохая практика. Это зависит от ваших вариантов использования. В этом случае я думаю, что использование defaultValue совершенно корректно. - person Ashitaka; 27.06.2016