我已经在React中编写了一个CRUD全栈任务应用程序。这与nodeJS API挂钩。该应用程序应该允许用户添加任务,删除任务以及更新在完成/未完成之间切换的类。
我设法使该应用程序正常工作,但我目前正在尝试通过将其拆分为单独的组件来进行重构。
重构前的工作示例
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import './styles/styles.scss';
class App extends React.Component {
constructor() {
super();
this.handleAddTask = this.handleAddTask.bind(this);
this.handleDeleteTask = this.handleDeleteTask.bind(this);
this.handleToggleComplete = this.handleToggleComplete.bind(this);
this.state = {
tasks: []
};
}
getTasks() {
axios.get('http://localhost:3000/tasks')
.then(response => {
this.setState({ tasks: response.data });
})
.catch(function (error) {
console.log(error);
});
}
handleAddTask(e) {
e.preventDefault();
const newTaskDescription = e.target.elements.task.value.trim();
if(newTaskDescription.length) {
axios.post('http://localhost:3000/tasks', {
description: newTaskDescription
}).then(() => {
this.getTasks();
});
e.target.elements.task.value = '';
}
}
handleDeleteTask(e) {
e.preventDefault();
const taskId = e.target.getAttribute('data-id');
axios.delete(`http://localhost:3000/tasks/${taskId}`)
.then(() => {
this.getTasks();
})
.catch(function (error) {
console.log(error);
});
}
handleToggleComplete(e) {
e.preventDefault();
const taskId = e.target.getAttribute('data-id');
const tasks = this.state.tasks;
const taskIndex = tasks.findIndex(task => task._id === taskId);
tasks[taskIndex].completed = !tasks[taskIndex].completed;
this.setState(() => {
return { tasks };
}, () => {
axios.put(`http://localhost:3000/tasks/${taskId}`, { completed: this.state.tasks[taskIndex].completed})
.then(() => {
this.getTasks();
})
.catch(function (error) {
console.log(error);
});
});
}
componentDidMount() {
this.getTasks();
}
render() {
return (
<div>
<h1>Here is a list of Tasks</h1>
<form onSubmit={this.handleAddTask}>
<input type="text" name="task"/>
<button>Add a task</button>
</form>
{this.state.tasks.length === 0 && <p>Please add a task to get started</p>}
<ul>
{
this.state.tasks.map((task) => {
return <li
key={task._id}
className={ task.completed ? 'completed' : '' }
>
{task.description}
<form
data-id={task._id}
onSubmit={this.handleToggleComplete}
>
<button>Toggle</button>
</form>
<form
data-id={task._id}
onSubmit={this.handleDeleteTask}
>
<button>Delete</button>
</form>
</li>;
})
}
</ul>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
重新分解后的示例
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import './styles/styles.scss';
class App extends React.Component {
constructor() {
super();
this.handleAddTask = this.handleAddTask.bind(this);
this.handleDeleteTask = this.handleDeleteTask.bind(this);
this.handleToggleComplete = this.handleToggleComplete.bind(this);
this.state = {
tasks: []
};
}
getTasks() {
axios.get('http://localhost:3000/tasks')
.then(response => {
this.setState({ tasks: response.data });
})
.catch(function (error) {
console.log(error);
});
}
handleAddTask(e) {
e.preventDefault();
const newTaskDescription = e.target.elements.task.value.trim();
if(newTaskDescription.length) {
axios.post('http://localhost:3000/tasks', {
description: newTaskDescription
}).then(() => {
this.getTasks();
});
e.target.elements.task.value = '';
}
}
handleDeleteTask(e) {
e.preventDefault();
const taskId = e.target.getAttribute('data-id');
axios.delete(`http://localhost:3000/tasks/${taskId}`)
.then(() => {
this.getTasks();
})
.catch(function (error) {
console.log(error);
});
}
handleToggleComplete(e) {
e.preventDefault();
const taskId = e.target.getAttribute('data-id');
const tasks = this.state.tasks;
const taskIndex = tasks.findIndex(task => task._id === taskId);
tasks[taskIndex].completed = !tasks[taskIndex].completed;
this.setState(() => {
return { tasks };
}, () => {
axios.put(`http://localhost:3000/tasks/${taskId}`, { completed: this.state.tasks[taskIndex].completed})
.then(() => {
this.getTasks();
})
.catch(function (error) {
console.log(error);
});
});
}
componentDidMount() {
this.getTasks();
}
render() {
return (
<div>
<h1>Here is a list of Tasks</h1>
<form onSubmit={this.handleAddTask}>
<input type="text" name="task"/>
<button>Add a task</button>
</form>
{this.state.tasks.length === 0 && <p>Please add a task to get started</p>}
<ul>
{
this.state.tasks.map((task) => {
return <Task
id={task._id}
key={task._id}
className={task.completed ? 'completed' : ''}
description={task.description}
handleDeleteTask={this.handleDeleteTask}
handleToggleComplete={this.handleToggleComplete}
/>;
})
}
</ul>
</div>
);
}
}
const Task = (props) => {
return (
<div>
{props.description}
<form
data-id={props._id}
onSubmit={props.handleToggleComplete}
>
<button>Toggle</button>
</form>
<form
data-id={props._id}
onSubmit={ props.handleDeleteTask}
>
<button>Delete</button>
</form>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('app'));
这是API数据的样子:
0: {completed: false, _id: "5d4eeb8c8925d7368654559d", description: "skaksjakjjsa", __v: 0}
1: {completed: true, _id: "5d4eeb968925d7368654559f", description: "abcdefghijklmnop", __v: 0}
2: {completed: true, _id: "5d4f0de930952a4064afa954", description: "akjkjskjaka", __v: 0}
3: {completed: false, _id: "5d4f10ae2faf70425804a3c4", description: "sasas", __v: 0}
4: {completed: false, _id: "5d4f10b22faf70425804a3c5", description: "ksksksksk", __v: 0}
5: {completed: false, _id: "5d4f10b62faf70425804a3c6", description: "dgdgdgdgdg", __v: 0}
6: {completed: false, _id: "5d4f12792faf70425804a3c7", description: "alallalal", __v: 0}
7: {completed: false, _id: "5d4f12822faf70425804a3c8", description: "abcdefghijklmnop", __v: 0}
问题在于,当我尝试触发这些函数时,将handleDeleteTask和handleToggleComplete函数作为道具传递下来之后,它说e.target.getAttribute('data-id')
是未定义的吗?但是据我所知,我已经在组件中定义了data-id属性?
任何帮助调试的人将不胜感激!
答案 0 :(得分:3)
在您的应用组件中,您将 _id 作为 id 传递。但是在Task组件中,您正在访问错误的道具。
下面是更正的代码。
Jun30 = {'File':['LB13-LP41-10-ZR.asc', 'LB13-LP41-19-ZR.asc', 'LB13-MB50-1-ZR.asc', 'LB13-MB50-18ZR.asc'],
'49Ti/30Si16O':[0.000405567, 0.000272094, 0.000320981, 0.000153742],
'1 se err':[2.61586E-06, 7.65216E-07, 1.32338E-06, 1.53561E-06]}
df30 = pd.DataFrame(Jun30)
df30.set_index('File', inplace = True)