Из самого названия. Я изучаю новое в React, и у меня проблема с полями редактирования.
Всякий раз, когда я нажимаю на определенный элемент для редактирования, остальные невыбранные элементы также будут редактироваться, как показано на скриншоте ниже. Мне было интересно, как я могу создать уникальные поля редактирования полей, которые будут редактировать только конкретное поле, выбранное в данный момент. Каждый раз, когда я ввожу новый элемент в editedField, я получаю такую ошибку.
Код
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Skills extends Component {
constructor(props) {
super(props);
this.state = {
skills : ["Frost Bolt", "Arcane Missle"],
skillField : '',
skiller : '',
editIsHidden : true,
editConfIsHidden : true,
editSkillField : '',
};
// Event Listeners
this.addSkill = this.addSkill.bind(this);
this.removeSkill = this.removeSkill.bind(this);
this.editSkill = this.editSkill.bind(this);
this.handleChangeEvent = this.handleChangeEvent.bind(this);
this.clearField = this.clearField.bind(this);
this.confirmEdit = this.confirmEdit.bind(this);
}
clearField() {
this.setState({
skillField : ''
});
}
handleChangeEvent(event, element) {
this.setState({
[element] : event.target.value
});
}
editSkill(editedSkill) {
this.setState({
editIsHidden : false
});
this.setState({
editConfIsHidden : false
});
}
confirmEdit(oldEditedSkill) {
let index = 0;
let skillsArray = this.state.skills;
let newEditedSkill = this.state.editSkillField;
this.state.skills.forEach(function(skill) {
if (skill == oldEditedSkill) {
skillsArray[index] = newEditedSkill;
console.info(newEditedSkill);
}
index++;
});
this.setState({
skills : skillsArray
});
this.setState({
editConfIsHidden : true
});
this.setState({
editIsHidden : true
});
console.info(this.state.skills);
}
addSkill() {
this.state.skills.push(this.state.skillField);
this.setState({
skills: this.state.skills
});
console.info(this.state.skills);
this.clearField();
}
removeSkill(removedSkill) {
let adr = 0;
let skillsArray = this.state.skills;
this.state.skills.forEach(function(skill) {
if (skill == removedSkill) {
skillsArray.splice(adr, 1);
}
adr++;
});
this.setState({
skills : skillsArray
});
}
render() {
const skillLists = this.state.skills.map((val) => {
return <li>{val}
<input onChange = {(e) => this.handleChangeEvent(e, "editSkillField")} value = {this.state.editSkillField} className = {this.state.editIsHidden ? 'hidden' : ''} />
<button onClick = {() => this.removeSkill(val)}>x</button>
<button onClick = {() => this.editSkill(val)}>e</button>
<button onClick = {() => this.confirmEdit(val)} className = {this.state.editConfIsHidden ? 'hidden' : ''} >ok</button>
</li>
});
return (
<div>
<input onChange = {(e) => this.handleChangeEvent(e, "skillField")} value = {this.state.skillField} />
<button onClick = {this.addSkill}>Add Skill</button>
<h4>Skills</h4>
<ul>{skillLists}</ul>
</div>
);
}
}
export default Skills;
🤔 А знаете ли вы, что...
React предлагает виртуальное DOM для оптимизации производительности при обновлении интерфейса.
Вам следует подумать о том, чтобы изменить его на такой объект, чтобы вы могли легко справиться с этим, и вам не нужно поддерживать другие свойства.
skills: [{ id: "Frost Bolt", value: '' }, { id: "Arcane Missle", value: '' }],
при изменении ввода попробуйте изменить так
handleChangeEventSkills(event, element) {
this.setState({
skills: this.state.skills.map(a => {
if (a.id === element) {
a.value = event.target.Value;
}
return a;
})
});
}
оставьте свой хендлмен как есть
handleChangeEvent(event, element) {
this.setState({
[element]:event.target.value
});
}
и назовите это во входных данных навыков, как это
<input onChange = {(e) => this.handleChangeEventSkills(e, val.id)}
value = {val.val} className = {this.state.editIsHidden ? 'hidden' : ''} />
Вот демо
Если вы внимательно посмотрите на код, в котором отображаются skills
, можно обнаружить, что имя класса hidden
включено или отключено для каждого элемента в списке, как в приведенном ниже коде.
<input onChange = {(e) => this.handleChangeEvent(e, "editSkillField")} value= {this.state.editSkillField} className = {this.state.editIsHidden ? 'hidden' : ''} />
Нам нужно сначала иметь состояние, которое сообщает, что конкретное рассматриваемое поле доступно для редактирования. Вы можете сделать это несколькими способами в зависимости от ваших требований. Вот один из способов сделать это.
Ваша функция editSkill
должна хранить skill
, который необходимо отредактировать. Что-то ниже будет работать.
editSkill(editedSkill) {
this.setState({
editIsHidden : editedSkill
});
this.setState({
editConfIsHidden : editedSkill
});
}
Затем ваш рендер немного изменится, как показано ниже.
const skillLists = this.state.skills.map((val) => {
return <li>{val}
<input onChange = {(e) => this.handleChangeEvent(e, "editSkillField")} value = {this.state.editSkillField} className = {(this.state.editIsHidden !== val) ? 'hidden' : ''} />
<button onClick = {() => this.removeSkill(val)}>x</button>
<button onClick = {() => this.editSkill(val)}>e</button>
<button onClick = {() => this.confirmEdit(val)} className = {(this.state.editConfIsHidden !== val) ? 'hidden' : ''} >ok</button>
</li>
});
Затем в вашей функции confirmEdit
сбросьте значения соответствующих переменных состояния, например
this.setState({
editConfIsHidden : null,
});
this.setState({
editIsHidden : null,
});
Это поможет вашему решению. Тем не менее, есть несколько вещей, которые следует учитывать.
Старайтесь поддерживать меньшее количество состояний. Я надеюсь, что состояния editConfIsHidden
и editIsHidden
можно будет заменить одним состоянием, если только у вас нет особых случаев использования их по отдельности.
Когда мы пытаемся установить состояние, мы можем использовать один вызов this.setState
вместо последовательного и многократного вызова setState
, как показано в этом ответе.