我正在学习React,目前正在尝试创建待办事项列表。一切正常,但是,当我尝试删除数组中的项目时,整个页面将重新呈现。
有人可以让我知道我哪里出错了吗?我只想在单击按钮后删除特定项目,而不是重新渲染整个页面。
代码:
import React, { Component } from "react";
import "./todo.css";
class Todo extends Component {
constructor(props) {
super(props);
this.state = {
task: "",
taskList: []
};
}
handleAdd = e => {
e.preventDefault();
this.setState({
task: "",
taskList: [...this.state.taskList, this.state.task]
});
};
onChange = e => {
this.setState({
task: e.target.value
});
};
handleDelete = task => {
console.log(task);
const newtaskList = this.state.taskList.splice(task, 1);
this.setState({
taskList: newtaskList
});
console.log(task);
};
render() {
return (
<form className='App'>
<div className='input input-group mb-3'>
<input
type='text'
className='form-control'
placeholder='Enter a task'
value={this.state.task}
onChange={this.onChange}
/>
<button className='btn btn-primary' onClick={this.handleAdd}>
ADD
</button>
</div>
<div className='output' id='output'>
<ul className='list-group'>
{this.state.taskList.map((task, index) => (
<li
className='list-group-item'
key={index}
style={{
display: "flex",
justifyContent: "space-between",
alignContent: "center"
}}>
{task}
<div className='input-group-prepend'>
<button
className='btn btn-danger'
onClick={() => this.handleDelete(task)}>
Done
</button>
</div>
</li>
))}
</ul>
</div>
</form>
);
}
}
答案 0 :(得分:1)
您可以在注释中看到模板中有一个表单。如果单击按钮,则模板中的表单将被提交,这将导致回发,即页面重新加载。因此,要么停止提交 (1) 形式,要么将按钮的类型更改为type="button"
:
<button type="button"
默认行为是type="submit"
,因此更改类型可以解决您的问题。
1。您没有任何表单提交事件。
答案 1 :(得分:1)
如果要避免在发生提交事件时刷新页面,则应使用preventDefault()
。
如果您想在React
中禁用整个页面的呈现,而仅重新呈现页面的某些部分,则可以使用两种解决方案:
与prevProps
内的prevState
或componentDidUpdate
进行类组件的额外比较:
componentDidUpdate(prevProps, prevState) {
if(prevState.taskList !== this.state.taskList) {
// do your magic here
}
}
useEffect()
钩在功能组件中:
如果在重新渲染之间某些值未更改,您可以告诉React跳过应用效果。为此,请将数组作为可选的第二个参数传递给useEffect:
useEffect(() => {
// do your magic here
}, [taskList]); // Only re-run the effect if taskList changes
您可以在official React documentation中找到有关此功能的更多信息。
答案 2 :(得分:0)
这是由评论中提到的在react组件中提交表单引起的,您应该使用e.preventDefault()来防止按钮Submit的默认行为:
...
<button
className='btn btn-danger'
onClick={(e) => {
e.preventDefault();
this.handleDelete(task)
}}>
Done
</button>
...
答案 3 :(得分:0)
Splice按索引删除一个元素并返回删除的元素,并在拼接后操纵原始数组。
您需要做的就是更改handleDelete
功能。事件函数的第一个参数是事件对象。因此,将其作为第一个参数传递,并将其他参数与之绑定。
您可以试试这个-
handleDelete = (e, index) => {
console.log(index);
e.preventDefault();
const copyTask = [...this.state.taskList];
copyTask.splice(index, 1); // Splice directly change the copyTask array.
this.setState({
taskList: copyTask
});
};
还要更改此行-
onClick={(e) => this.handleDelete(e, index)}
第一个参数是event
对象。然后传递项目以外的索引。
答案 4 :(得分:0)
1。您正在使用html的form
元素。并且由于您正在使用其中的按钮,因此您需要添加e.preventDefault
,否则它将像提交并刷新页面一样。
2。在handleDelete
中传递参数时,您既未传递event
,也未传递index
。要使用splice
,您需要元素的index
。
3。作为回应,我建议使用spread operator
,它不会使状态发生变化。
因此,请替换这两件事。
handleDelete = (e , index) => {
e.preventDefault();
const { taskList } = this.state;
this.setState({
taskList: [...taskList.slice(0 , index) , ...taskList.slice(index + 1)]
});
};
并且,在调用句柄删除功能时,
onClick={(e) => this.handleDelete(e, index)}
并且,关于重新渲染。如果该组件中的任何状态被更改,React都会始终重新渲染该组件。在这里,删除时任务列表状态正在更改。因此组件正在重新渲染。