Я пытаюсь сделать динамические вкладки в Material-ui.Моя сфера деятельности - конференции.Конференция длится X дней, и каждый день проводится несколько сеансов.
Мне нужен какой-то способ показать эти сеансы во вкладках, используя Material-ui.Поскольку количество дней, в течение которых конференция работает, не является фиксированным, мне нужно, чтобы количество вкладок менялось.Кроме того, на каждой вкладке я хочу показать сеансы за день.
Я использую GraphQL, Apollo, React и Material-Ui.
У меня определена следующая схема GraphQL:
export default `
scalar Date
enum SortDirection {
ASCENDING
DESCENDING
}
enum SortableSessionField {
start_date
}
type Conference {
id: ID!
title: String!
address: String!
start_date: String
end_date: String
sessions: [Session]
}
type Paper{
id: ID!
title: String!
}
type Session {
conference_session_id: ID!
session_title: String
session_no: String
chair_name: String
discussant_1_name: String
discussant_2_name: String
room_description:String
start_date: String
start_time: String
end_time: String
papers: [Paper]
}
type Query {
conferences: [Conference!]!
sessions(conferenceId: ID!, day: String!
sort: SortDirection = DESCENDING
sortBy: SortableSessionField = start_date): [Session]
conference(id: ID!): Conference
session(id: ID!): Session
}
`;
Интересная функция здесь:
sessions(conferenceId: ID!, day: String!
sort: SortDirection = DESCENDING
sortBy: SortableSessionField = start_date): [Session]
, которая с учетом идентификатора конференции и даты возвращает все сеансы для конференции в этот день.Тестируя на площадке Graphql, он возвращает правильные данные.
У меня есть следующая базовая страница React:
import React from 'react'
import FullWidthTabs from '../components/Sessions'
class SessionsPage extends React.Component {
render() {
return (
<div>
<FullWidthTabs days={['2018-06-11', '2018-06-12', '2018-06-13']}/>
</div>
);
}
}
export default (SessionsPage);
в основном это просто отправка трех дат на страницу FullWidthTabs, которую я просто украл напрямуюиз Material-UI и изменены в соответствии с моими потребностями:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import SwipeableViews from 'react-swipeable-views';
import AppBar from '@material-ui/core/AppBar';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import Typography from '@material-ui/core/Typography';
import gql from 'graphql-tag'
import { graphql } from 'react-apollo'
import { Query } from 'react-apollo'
import SessionTab from '../components/SessionTab'
function TabContainer( { children }) {
return (
<Typography component="div" style={{padding: 8 * 3}}>
{children}
</Typography>
);
}
TabContainer.propTypes = {
children: PropTypes.node.isRequired,
dir: PropTypes.string.isRequired,
};
const styles = theme => ({
root: {
backgroundColor: theme.palette.background.paper,
width: 500,
},
});
class FullWidthTabs extends React.Component {
state = {
value: 0,
};
handleChange = (event, value) => {
this.setState({value});
}
;
handleChangeIndex = index => {
this.setState({value: index});
}
;
render() {
const tabs = this.props.days.map((day) => {
return (<Tab key={day.gridIndex} label={day} />)
});
const content = this.props.days.map((day) => {
return (<TabContainer><SessionTab conferenceId = "57" day={day}/></TabContainer>)
});
const {classes, theme} = this.props;
return (
<div className={classes.root}>
<AppBar position="static" color="default">
<Tabs
value={this.state.value}
onChange={this.handleChange}
indicatorColor="primary"
textColor="primary"
variant="fullWidth"
>
{ tabs }
</Tabs>
</AppBar>
<SwipeableViews
axis={theme.direction === 'rtl' ? 'x-reverse' : 'x'}
index={this.state.value}
onChangeIndex={this.handleChangeIndex}
>
{ content }
</SwipeableViews>
</div>
);
}
}
FullWidthTabs.propTypes = {
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
};
export default withStyles(styles, {withTheme: true})(FullWidthTabs);
Этот компонент получает (в данном случае) три даты из HOC, должен инициализировать три вкладки и поместить некоторую информацию о сеансе на каждую вкладку.
Компонентом для отображения данных сеанса является SessionTab:
import React from 'react'
import gql from 'graphql-tag'
import { graphql } from 'react-apollo'
import { Query } from 'react-apollo'
import ConferenceCard from '../components/ConferenceCard';
const SESSIONS_QUERY = gql`
query sessions($id: ID!, $day: String!){
sessions(conferenceId: $id, day: $day)
{conference_session_id
session_title
start_date
start_time
end_time
}
}
`
class SessionsTab extends React.Component {
constructor(props) {
super(props);
console.log(props);
}
render() {
let id = this.props.conferenceId;
let day = this.props.day;
console.log("SessionTab " + id + " " + day);
return (
<Query query={SESSIONS_QUERY} variables={{id, day}}>
{({ loading, error, data }) => {
if (loading)
return <div>Fetching</div>
if (error)
return <div>Error</div>
const sessionsToRender = data.sessions
return (
<div>
{sessionsToRender.map(session => <div> {session.conference_session_id} </div>)}
</div>
)
}}
</Query>
)
}
}
export default (SessionsTab);
sessionTab получает идентификатор конференции и данные и находит все сеансы за день.При тестировании в GraphQL игровая площадка работает.
Каждый SessionTab инициализируется в FullWidthTab следующим образом:
const content = this.props.days.map((day) => {
return (<TabContainer><SessionTab conferenceId = "57" day={day}/></TabContainer>)
});
, где реквизиты дней содержат даты, переданные со страницы сеанса.
Но, похоже, это не работает.
Мои вопросы:
1) это правильный способ сделать что-то?2) при запуске tab1 показывает данные, в то время как tab2 и tab3 показывают ошибку.
Я не знаю, что это неправильно, но похоже, что SessionTab неправильно инициализирован, за исключением первого.
Ким