Я новичок в области React и обучения благодаря созданию простого приложения для составления расписания, которое пользователи могут заполнять, и при его отправке оно отправляет данные в список SharePoint с помощью API-интерфейса SharePoint (см. Ниже).
Как я хочу, чтобы это работало Инструмент создан с использованием таблицы, и каждая строка является строкой таблицы, хранящейся в дочернем компоненте. Когда пользователь нажимает кнопку «Добавить задачу», это создает новую строку таблицы, в которую он может добавить время, которое он завершил для этой отдельной задачи. Они могут добавлять столько элементов, сколько им нужно, затем, когда они нажимают кнопку «Отправить», каждая отдельная задача отправляется в список Sharepoint в виде отдельных элементов.
Моя проблема В данный моменткогда пользователь добавляет задачу, затем добавляет текст в поле ввода. Он передается в родительское состояние, в которое необходимо будет отправить данные, но это означает, что когда вы вводите текст в одну из строк, он отражается во ВСЕХ строках. Когда я сохраняю данные в локальном состоянии, невозможно передать значения в родительское состояние, поэтому все задачи можно отправить одним щелчком мыши, но сохранить уникальные значения. Я хочу знать, есть ли в любом случае значения для каждой строки, которые будут сохранены в локальном состоянии компонентов, чтобы они были уникальными, но чтобы передать значение в родительское состояние, чтобы их можно было отправлять вместе? Или как правильно с этим справляться в React?
Код Итак, у меня есть родительский компонент под названием TimesheetTool, который включает в себя пустой массив задач и основную таблицу (каждую задачу). пользователь хочет добавить к расписанию инструмент добавляется в виде строки таблицы). Затем внутри тела таблицы я сопоставил tr для извлечения строки таблицы из дочернего компонента с именем TableRow.
Родительский компонент
import * as React from 'react';
import styles from './TimesheetTool.module.scss';
import { ITimesheetToolProps } from './ITimesheetToolProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { ISpfxReactCrudState } from './ISpfxReactCrudState';
import { IListItem } from './IListItem';
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
import TableRow from './TableRow';
export default class TimesheetTool extends React.Component<ITimesheetToolProps, ISpfxReactCrudState> {
constructor(props: ITimesheetToolProps, state: ISpfxReactCrudState) {
super(props);
this.state = {
project:'', task:'', mon:0, tues:0, wed:0, thurs:0, fri:0, sat:0, sun:0,
status: 'Ready',
items: [],
tasks: []
};
}
handleProjectChange = (event) => {this.setState({project: event.target.value}); console.log('Event:', event.target.value)}
handleTaskChange = (event) => {this.setState({task: event.target.value})};
handleMonChange = (event) => {this.setState({mon: event.target.value})};
handleTuesChange = (event) => {this.setState({tues: event.target.value})};
handleWedChange = (event) => {this.setState({wed: event.target.value})};
handleThursChange = (event) => {this.setState({thurs: event.target.value})};
handleFriChange = (event) => {this.setState({fri: event.target.value})};
handleSatChange = (event) => {this.setState({sat: event.target.value})};
handleSunChange = (event) => {this.setState({sun: event.target.value})};
handleAddTask = (task) => {
task.preventDefault();
const tasks = [...this.state.tasks];
this.setState({ tasks: this.state.tasks.concat(task) });
}
handleDelete = (index) => () => this.setState({tasks: this.state.tasks.filter((_, i) => i !== index)})
public render(): React.ReactElement<ITimesheetToolProps > {
const items: JSX.Element[] = this.state.items.map((item: IListItem, i: number): JSX.Element => {
return (
<li>{item.Title} ({item.Id}) </li>
);
});
return (
<div>
<form>
<button onClick={this.handleAddTask} >Add a Task</button>
<table className={styles.table}>
<thead>
<tr>
<th>Project</th>
<th>Task</th>
<th>Monday</th>
<th>Tuesday</th>
<th>Wednesday</th>
<th>Thursday</th>
<th>Friday</th>
<th>Saturday</th>
<th>Sunday</th>
</tr>
</thead>
<tbody>
{this.state.tasks.map((task, index) =>
<tr key={index}>
<TableRow
handleProjectChange={this.handleProjectChange}
handleTaskChange = {this.handleTaskChange}
handleMonChange = {this.handleMonChange}
handleTuesChange = {this.handleTuesChange}
handleWedChange = {this.handleWedChange}
handleThursChange = {this.handleThursChange}
handleFriChange = {this.handleFriChange}
handleSatChange = {this.handleSatChange}
handleSunChange = {this.handleSunChange}
project={this.state.project}
task={this.state.task}
mon={this.state.mon}
tues={this.state.tues}
wed={this.state.wed}
thurs={this.state.thurs}
fri={this.state.fri}
sat={this.state.sat}
sun={this.state.sun}
/>
<td><a href="#" onClick={this.handleDelete(index)}>Delete</a></td>
</tr>
)}
</tbody>
</table>
<div>
<a href="#" onClick={() => this.createItem()}><span>Submit</span> </a>
</div>
</form>
<div>
{this.state.status}
<ul>
{items}
</ul>
</div>
</div>
);
}
private createItem(): void {
this.setState({
status: 'Creating item...',
items: []
});
const body: string = JSON.stringify({
'Title': `Submitted: ${new Date()}`,
'Project': `${this.state.project}`,
'Task': `${this.state.task}`,
'Monday': `${this.state.mon}`,
'Tuesday': `${this.state.tues}`,
'Wednesday': `${this.state.wed}`,
'Thursday': `${this.state.thurs}`,
'Friday': `${this.state.fri}`,
'Saturday': `${this.state.sat}`,
'Sunday': `${this.state.sun}`
});
this.props.spHttpClient.post(`${this.props.siteUrl}/_api/web/lists/getbytitle('${this.props.listName}')/items`,
SPHttpClient.configurations.v1,
{
headers: {
'Accept': 'application/json;odata=nometadata',
'Content-type': 'application/json;odata=nometadata',
'odata-version': ''
},
body: body
})
.then((response: SPHttpClientResponse): Promise<IListItem> => {
return response.json();
})
.then((item: IListItem): void => {
this.setState({
status: `Timesheet Successfully Submitted`,
items: []
});
}, (error: any): void => {
this.setState({
status: 'Error while submitting timesheet' + error,
items: []
});
});
}
}
Дочерний компонент
import * as React from 'react';
import { Component, createRef } from 'react';
import { ITimesheetToolProps } from './ITimesheetToolProps';
import { ISpfxReactCrudState } from './ISpfxReactCrudState';
export default class TableRow extends React.Component<ITimesheetToolProps, ISpfxReactCrudState> {
render() {
return (
<React.Fragment>
<td><input type="text" name="project" value={this.props.project} onChange={(event) => this.props.handleProjectChange(event)} /></td>
<td><input type="textarea" name="task" value={this.props.task} onChange={(event) => this.props.handleTaskChange(event)} /></td>
<td><input type="number" name="mon" value={this.props.mon} onChange={(event) => this.props.handleMonChange(event)} /></td>
<td><input type="number" name="tues" value={this.props.tues} onChange={(event) => this.props.handleTuesChange(event)} /></td>
<td><input type="number" name="wed" value={this.props.wed} onChange={(event) => this.props.handleWedChange(event)} /></td>
<td><input type="number" name="thurs" value={this.props.thurs} onChange={(event) => this.props.handleThursChange(event)} /></td>
<td><input type="number" name="fri" value={this.props.fri} onChange={(event) => this.props.handleFriChange(event)}/></td>
<td><input type="number" name="sat" value={this.props.sat} onChange={(event) => this.props.handleSatChange(event)} /></td>
<td><input type="number" name="sun" value={this.props.sun} onChange={(event) => this.props.handleSunChange(event)} /></td>
</React.Fragment>
)
}
}