Создавая приложение React, я хочу сделать свой код максимально сухим. Я впервые начал использовать Typescript в этом проекте, и я столкнулся с проблемой повторного использования моих компонентов, где JSX может быть одинаковым для разных случаев, но типы и интерфейсы меняются.
Вот реальный пример: приведенный ниже код представляет собой компонент React, созданный с использованием TypeScript, Apollo / GraphQL и Redux. Он возвращает таблицу всех футбольных команд в моей БД, полученную из бэкэнд-API.
Дело в том, что я хотел бы использовать этот же компонент для отображения таблицы игр, таблицы игроков и т. Д.
И я застрял, например, с моим Team
интерфейсом. Каждая команда имеет только id
и name
; но каждая игра имеет date
, homeTeam
и awayTeam, a
Score` и т. д.
Следовательно, как я могу управлять своими интерфейсами и типами, чтобы я мог повторно использовать этот компонент?
import React from 'react';
import { connect } from 'react-redux';
import { setView, toggleDeleteElemModal } from '../../redux/actions';
import gql from 'graphql-tag';
import { Query } from 'react-apollo';
import { ApolloError } from 'apollo-client';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faInfo, faEdit, faTrash } from '@fortawesome/free-solid-svg-icons';
interface SectionTableProps {
setView: typeof setView
toggleDeleteElemModal : typeof toggleDeleteElemModal
}
interface Team {
id: string;
name: string;
}
interface Data {
allTeams?: Team[];
}
interface SectionTableQueryProps {
allTeams: Team[];
error?: ApolloError;
loading: boolean;
}
const GET_ALL_TEAMS = gql`
query {
allTeams {
id
name
}
}
`;
class SectionTableQuery extends Query<Data, {}> {}
const SectionTable = (props: SectionTableProps) => (
<table className="table table-hover table-responsive">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Actions</th>
</tr>
</thead>
<SectionTableQuery query={GET_ALL_TEAMS}>
{({ data: { allTeams = [] } = {}, error, loading }) => {
if (loading) {
return <tbody><tr><td>LOADING</td></tr></tbody>
};
if (error !== undefined) {
return <tbody><tr><td>ERROR</td></tr></tbody>
};
return (
<tbody>
{allTeams.map((team: Team) => (
<tr key={team.id}>
<th scope="row">{team.id}</th>
<td>{team.name}</td>
<td className="d-flex justify-content-between">
<div onClick={() => props.setView("info")}>
<FontAwesomeIcon icon={faInfo} />
</div>
<div onClick={() => props.setView("edit")}>
<FontAwesomeIcon icon={faEdit} />
</div>
<div onClick={() => props.toggleDeleteElemModal()}>
<FontAwesomeIcon icon={faTrash} />
</div>
</td>
</tr>
))}
</tbody>
);
}}
</SectionTableQuery>
</table>
)
const mapDispatchToProps = { setView, toggleDeleteElemModal }
export default connect(null, mapDispatchToProps)(SectionTable);