React при обработке события перезатирается state

112
30 августа 2021, 21:50

В родительском компоненте есть инициализация state

state = { 
  tasks: {},
  users: {
    userId: 1,
    userName: "Artem Gavrilov",    
  },
  appData: {
    selectedDate: new Date(),
    unfinished: {},
  }, 
};

Есть дочерний компонент с формой из текстовых инпутов.

export default class Form extends React.Component { 
  handleTextChange = (e) => { 
    e.preventDefault(); 
    const {name, value} = e.target; 
    this.setState({...this.state, appData: { 
      unfinished: { 
        [name]: value, 
        } 
      } 
    }); 
  } 
  render() { 
    return ( 
      <div className="task-container"> 
        <form className="task-form"> 
          <div className="task-line"> 
            <p className="task-p">Название задачи</p> 
            <input onChange={this.handleTextChange} className="task-input" type="text" required name="taskName"/> 
          </div> 
          <div className="task-line"> 
            <p className="task-p">Описание задачи</p> 
            <textarea onChange={this.handleTextChange} className="task-textarea" cols="20" rows="5" type="text" required name="taskDesc"/> 
          </div> 
        </form> 
      </div> 
    ); 
  } 
}  

Я хочу заполнять объект state.appData.unfinished текущими значениями из инпутов. Проблема в том, что при вводе символов во втором поле - state перезатирается и я теряю значение из первого (и наоборот). Если я записываю в state.[name], все работает корректно, но мне хочется работать с такой структурой состояния. Как перестать перезатирать состояние во вложенном объекте?

Answer 1

В принципе идея в правильном направлении, но есть небольшой нюанс, вот пример с сохранением state без его перезаписывания:

class Form extends React.Component { 
 
  constructor(props) { 
    super(props); 
     
    // засетим значение по-умолчанию, хотя бы пустой объект 
    this.state = { 
      appData: { 
        unfinished: {}, 
      }, 
    };  
  } 
 
  handleTextChange = (e) => { 
    e.preventDefault(); 
    const { name, value } = e.target; 
 
    // сохранение значения в объекте стейта 
    this.setState(prevState => ({ 
      appData: { 
        unfinished: { 
          ...prevState.appData.unfinished, // объединяем предыдущее значение с новым значением (копируем объект) 
          [name]: value, // перезапишем проперти `[name]` в копии объекта `prevState.appData.unfinished`) 
        } 
      } 
    })); 
  } 
   
  showStateToConsole = () => { 
    console.log(this.state); 
  } 
   
  render() { 
    return ( 
      <div className="task-container"> 
        <form className="task-form"> 
          <div className="task-line"> 
            <p className="task-p">Название задачи</p> 
            <input 
              onChange={this.handleTextChange} 
              className="task-input" 
              type="text" 
              required 
              name="taskName" 
            /> 
          </div> 
          <div className="task-line"> 
            <p className="task-p">Описание задачи</p> 
            <textarea 
              onChange={this.handleTextChange} 
              className="task-textarea" 
              cols="20" 
              rows="5" 
              type="text" 
              required 
              name="taskDesc" 
            /> 
          </div> 
        </form> 
        <button onClick={this.showStateToConsole}>Show state in console...</button> 
      </div> 
    ); 
  } 
} 
 
ReactDOM.render( 
  <Form />, 
  document.getElementById('container') 
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> 
<div id="container"> 
  <!-- This element's contents will be replaced with your component. --> 
</div>

Есть очень хороший пример с массой примеров на enSO: Updating an object with setState in React

READ ALSO
Альтернатива Array.prototype.find()

Альтернатива Array.prototype.find()

Есть ли альтернатива методу Arrayprototype

108
Javascript/NodeJS разбивка строки по формату

Javascript/NodeJS разбивка строки по формату

Допустим есть строка вида aaaa|qqqq|www|bbbb;ccc Я хочу задать формат в виде $1|$2|$name|$4;$5 И получить объект согласно описанному выше формату с такими же ключамиПодразумевается...

227
Не запускается скрипт для вывода правильной последовательности скобок

Не запускается скрипт для вывода правильной последовательности скобок

Есть код на для вывода правильной последовательности n элементов, переписал его под python, но он не работаетВ чём моя ошибка?

158
new (функция конструктор)

new (функция конструктор)

Когда вызываешь функцию с new, то берется конструктор этой функции и создается объектКак можно вызвать такую функцию так, чтобы она вернула...

186