这是我的第一篇文章。 我正在创建todo应用程序。 当点击加号按钮时,我的应用程序正在向任务列表中添加新任务,并且在几次点击之后你得到的任务很简单,但问题是每个任务都有删除图标,遗憾的是由于我缺乏足够的技能而删除了所有组件而不是一个,哪个图标属于。
这是App.js代码
class App extends React.Component {
constructor(props){
super(props);
this.handleDelete = this.handleDelete.bind(this);
this.addTask = this.addTask.bind(this);
this.state = {taskNum: 0,
delete: false
}
}
addTask(){
this.setState({
taskNum: this.state.taskNum +1,
delete:false
});
}
handleDelete(e){
console.log(e.target);
this.setState({delete: true});
}
render() {
const tasks = [];
for (let i = 0; i < this.state.taskNum; i += 1) {
tasks.push(!this.state.delete && <Task key={i} number={i} deleteTask={this.handleDelete}/>);
};
return (
<div className="ui container content">
<h2 className="centerHeader header">TODO LIST</h2>
<h3 className="taskheader secondaryHeader">Tasks <Icon className="addNew plus" action={this.addTask}/></h3>
<div className="ui container five column grid taskList">
{tasks}
</div> ...
这里是Task.js
export class Task extends React.Component {
constructor(props){
super(props);
this.dataChanged = this.dataChanged.bind(this);
this.state ={message: 'TASK' + (this.props.number+1),
}
}
customValidateText(text) {
return (text.length > 0 && text.length < 31);
}
dataChanged(data) {
console.log(data.message);
this.setState({message: data.message});
}
render(){
const centerRow = classNames('textCenter', 'row');
return (<div className="ui column task">
<div className={centerRow}><InlineEdit
validate={this.customValidateText}
activeClassName="editing"
text={this.state.message}
paramName="message"
change={this.dataChanged}
style={{
background: 'inherit',
textAlign:'center',
maxWidth: '100%' ,
display: 'inline-block',
margin: 0,
padding: 0,
fontSize: '1em',
outline: 0,
border: 0
}}
/></div>
<div className={centerRow}><Icon className="browser outline huge center"/> </div>
<div className={centerRow}><Icon className="large maximize"/><Icon className="large save saveTask"/><Icon className="large trash outline" action={this.props.deleteTask} /></div>
</div>
);
我想过尝试e.target并选择parentNode但我不确定这是否是正确的解决方案,因为使用react,所以你可以帮我找到这个问题的有效解决方案,这样当点击垃圾图标时它会删除只有父组件。
答案 0 :(得分:0)
反应强大的一个主要原因是,它使您能够根据您的数据维护DOM,而无需自己对DOM进行任何操作
因此,为了让你的例子更加友好,你需要做一些改变,这也将解决你的问题
1-您需要保持数据的实际状态,因此添加待办事项表示添加到程序中的实际实际数据,而不仅仅是组件表示。
2-删除由component
表示的任务意味着删除它自己的数据,因此删除其中一个任务意味着删除其实际数据,然后反应将处理为您更新DOM,所以想法隐藏组件的标志不是React JS方式
3-反应方式知道何时呈现以及如何处理所有数据由组件state
管理..因此您将数据保存在组件state
中,您只需要关心更新state
,然后反应将知道它将需要再次渲染,但现在使用新的更新任务列表
我在代码中做了一些更改,并用注释行解释原因
class App extends React.Component {
constructor(props){
super(props);
this.handleDelete = this.handleDelete.bind(this);
this.addTask = this.addTask.bind(this);
this.state = {
tasks: [ ], // this is the array that will hold the actual data and based on its content react will handle rendering the correct data
counter : 1 // this counter is incremented every task addition just to make sure we are adding different task name just for the example explanation
}
}
}
addTask(){
this.setState({
tasks: this.state.tasks.push( "TASK" + counter); //This how we add a new task as i said you are adding an actual task data to the state
counter : this.state.counter + 1 //increment counter to have different task name for the next addition
});
}
//i changed this function to accept the task name so when you click delete it will call this function with task name as parameter
//then we use this task name to actually remove it from the tasks list data in our state
handleDelete(taskToDelete){
this.setState({
//the filter function below will remove the task from the array in our state
//After this state update, react will render the component again but now with the tasks list after removing deleting this one
tasks : this.state.tasks.filter((task) => {
if(task != taskToDelete)
return word;
})
});
}
render() {
const tasks = [];
//Notice here we pass an actual data to every Task component so i am adding prop message to take the value from this.state.tasks[index]
for (let i=0 ; i< this.state.tasks.length ; i++)
{
tasks.push(<Task key={i} message={this.state.tasks[i]} deleteTask={this.handleDelete}/>);
}
return (
<div className="ui container content">
<h2 className="centerHeader header">TODO LIST</h2>
<h3 className="taskheader secondaryHeader">Tasks <Icon className="addNew plus" action={this.addTask}/></h3>
<div className="ui container five column grid taskList">
{tasks}
</div> ...
)
}
}
任务组件
export class Task extends React.Component {
constructor(props){
super(props);
this.dataChanged = this.dataChanged.bind(this);
this.removeCurrentTask = this.removeCurrentTask.bind(this);
//Here i am setting the state from the passed prop message
this.state ={
message: this.props.message
}
}
customValidateText(text) {
return (text.length > 0 && text.length < 31);
}
dataChanged(data) {
console.log(data.message);
this.setState({message: data.message});
}
removeCurrentTask (){
//calling the deleteTask function with the current task name.
this.props.deleteTask(this.state.message);
}
render(){
const centerRow = classNames('textCenter', 'row');
return (
<div className="ui column task">
<div className={centerRow}><InlineEdit
validate={this.customValidateText}
activeClassName="editing"
text={this.state.message}
paramName="message"
change={this.dataChanged}
style={{
background: 'inherit',
textAlign:'center',
maxWidth: '100%' ,
display: 'inline-block',
margin: 0,
padding: 0,
fontSize: '1em',
outline: 0,
border: 0
}}
/></div>
<div className={centerRow}><Icon className="browser outline huge center"/> </div>
//Notice the action handler here is changed to use removeCurrentTask defined in current component
//BTW i don't know how Icon is handling the action property ... but now you can simply use onClick and call removeCurrentTask
<div className={centerRow}><Icon className="large maximize"/><Icon className="large save saveTask"/><Icon className="large trash outline" action={this.removeCurrentTask} /></div>
</div>
);
}
}