Как изменять свойства объекта state с сохранением предыдущий значений
Суть: Есть 4 поля куда вводятся значения, необходимо записать эти значения.
Проблема: При каждом вызове обработчика события происходит перезапись всего объекта с изменением значения одного свойства, остальные значения свойств равны 0, не сохраняются значения введенные в другие поля.
class BlockInput extends Component {
constructor(props){
super(props);
this.state = {
data: {
width: 0,
length: 0,
thickness: 0,
height: 0
}
}
this.clickChange = this.clickChange.bind(this);
}
clickChange(event){
const keysState = Object.keys(this.state.data);
keysState.map(item => {
if (event.target.name === item) {
this.setState(prevState=>({data: {...prevState.data, [item]: event.target.value}}));
}
})
console.log(this.state.data)
}
render(){
const {name, id, className} = this.props;
return (
<Input type="text" onChange={this.clickChange} name={id} autocomplete="off" placeholder="0 см" ></Input>
)
}
}
Ввожу в поле width консоль отвечает: width: '2', length: 0, thickness: 0, height: 0
После ввожу в поле length консоль отвечает: width: 0, length: '2', thickness: 0, height: 0
Ответы (2 шт):
Попробуйте заменить функцию обработчик вот так:
clickChange(event){
if (this.state.data.hasOwnProperty(event.target.name)) {
const upd = {};
upd[event.target.name] = event.target.value;
this.setState({data: { ...this.state.data, ...upd}})
}
}
В такой конструкции spread оператор будет работать правильно и мержить значения.
Так же для события нажатия кнопки, орагнизовывать цикл map по всем ключам - скажем так, лишнее
Так же в рендере надо Input присваивать значение из state
render(){
const {name, id, className} = this.props;
return (
<Input type="text" onChange={this.clickChange} name={id} autocomplete="off" placeholder="0 см" value={this.state.data[id]}></Input>
)
}
К какому выводу я пришел: Нельзя изменить state компонента (в моем случае input), для всех экземпляров этого компонента, state устанавливается только для конкретного экземпляра. Для установки значений всех экземпляров компонента в state, необходимо устанавливать state в компоненте-сборщике компонентов input, в котором вызываются все, в моем случае 4 компонента-input.
Код выглядит след образом:
class BlockInput extends Component {
clickChange = (event) => {
const arr = {}
arr[event.target.name] = event.target.value;
this.props.valueNum(arr)
}
render(){
const {name, id, className} = this.props;
return (
<DivInput className={className}>
<SpanText>{name}</SpanText>
<Input type="text" onChange={this.clickChange} name={id} autoСomplete="off" placeholder="0 см"></Input>
</DivInput>)
}}
export default class Corner extends Component {
constructor(props){
super(props);
this.state = {
names: { width: 'Ширина',
length: 'Длина',
thickness: 'Толщина',
height: 'Высота'
},
values: {
width: 0,
length: 0,
thickness: 0,
height: 0
}
}
}
getValue = (id) => {
return this.setState({values: { ...this.state.values, ...id}})
}
render(){
const {width, length, thickness, height} = this.state.names;
return (
<>
<div className="d-flex justify-content-center align-items-center transition" >
<BlockInput id ={'width'} name={width} className={'inputWidth'} valueNum={this.getValue}></BlockInput>
<BlockInput id ={'length'} name={length} className={'inputLength'} valueNum={this.getValue}></BlockInput>
<BlockInput id ={'thickness'} name={thickness} className={'inputThickness'} valueNum={this.getValue}></BlockInput>
<BlockInput id ={'height'} name={height} className={'inputHeight'} valueNum={this.getValue}></BlockInput>
<YourSvg className="svg"></YourSvg>
</div>
</>
)
}
}
Нахожусь в стадии обучения, код рабочий, но далеко не идеальный