Context:
class Table extends React.Component {
render() {
return (
<table>
<tr>
<Columns />
</tr>
</table>
);
}
}
<Columns /> would need to return multiple <td> elements in order for the rendered HTML to be valid. If a parent div was used inside the render() of <Columns />, then the resulting HTML will be invalid.class Columns extends React.Component {
render() {
return (
<div>
<td>Hello</td>
<td>World</td>
</div>
);
}
}
In order to solve this issue, we have to use React fragments.
class Columns extends React.Component {
render() {
return (
<React.Fragment>
<td>Hello</td>
<td>World</td>
</React.Fragment>
);
}
}
which results in a correct
<Table /> output of:<table>
<tr>
<td>Hello</td>
<td>World</td>
</tr>
</table>
import * as React from "react";
import CSSModules from "react-css-modules";
import { connect } from "react-redux";
import ReactTable from "react-table";
import {
Breadcrumb,
Button,
Dimmer,
Icon,
Input,
Loader,
Table
} from "semantic-ui-react";
import { repsActions } from "../_actions";
import AdminPageTable from "../_components/AdminPageTable";
import { GreenLed, RedLed } from "../_components/Leds";
import { WrappedButton } from "../_components/WrappedButton";
import { history } from "../_helpers";
const styles = require("./AdminPage.less");
const options = {
allowMultiple: true
};
interface SelectedHealthCheck {
name: string;
index: number;
display: boolean;
}
interface AdminPageState {
displayHealthCheck: SelectedHealthCheck;
}
interface AdminPageProps {
displayHealthCheck: boolean;
getAllReps: () => any;
reps: any;
}
@CSSModules(styles, options)
class ConnectedAdminPage extends React.Component<
AdminPageProps,
AdminPageState
> {
constructor(props) {
super(props);
this.state = {
displayHealthCheck: { name: null, index: 0, display: false }
};
}
public componentDidMount() {
this.props.getAllReps();
}
public handleNav = e => {
e.preventDefault();
history.push("/");
};
public handleCellClick = (selected, idx) => {
if (this.state.displayHealthCheck.name === selected) {
this.setState(prevState => ({
displayHealthCheck: {
name: selected,
index: idx,
display: !prevState.displayHealthCheck.display
}
}));
} else {
this.setState({
displayHealthCheck: { name: selected, index: idx, display: true }
});
}
};
public render() {
const {
reps: { reps }
} = this.props;
const { displayHealthCheck } = this.state;
if (!reps) {
return null;
}
if (reps.loading) {
return (
<Dimmer active>
<Loader>Loading</Loader>
</Dimmer>
);
}
if (reps.error) {
return <div>Error! {reps.error.message}</div>;
}
return (
<div styleName="page-container">
<div styleName="header-row ">
<div styleName="item">
<div styleName="title">Admin</div>
<Breadcrumb styleName="breadcrumb-container">
<Breadcrumb.Section onClick={this.handleNav}>
Dashboard
</Breadcrumb.Section>
<Breadcrumb.Divider />
<Breadcrumb.Section>Admin</Breadcrumb.Section>
</Breadcrumb>
</div>
<div styleName="btn-container">
<Button
id="override-button"
styleName="button-override"
onClick={this.props.getAllReps}
size="small"
>
<Icon name="refresh" />
Refresh
</Button>
</div>
</div>
<div styleName="admin-table-container">
<Table basic="very">
<Table.Header>
<Table.Row>
<Table.HeaderCell />
<Table.HeaderCell width={1}>Name</Table.HeaderCell>
<Table.HeaderCell width={1}>Display Name</Table.HeaderCell>
<Table.HeaderCell width={1}>Provisioner State</Table.HeaderCell>
<Table.HeaderCell width={1}>Version</Table.HeaderCell>
<Table.HeaderCell width={1}>Status</Table.HeaderCell>
<Table.HeaderCell />
</Table.Row>
</Table.Header>
<Table.Body>
{reps.map((rep, index) => {
return (
<AdminPageTable
rep={rep}
handleCellClick={this.handleCellClick}
displayHealthCheck={displayHealthCheck}
index={index}
/>
);
})}
</Table.Body>
</Table>
</div>
</div>
);
}
}
function mapDispatchToProps(dispatch) {
return {
getAllReps: () => {
dispatch(repsActions.getAllwithHealthStatus());
}
};
}
const mapStateToProps = state => {
const { reps } = state;
return {
reps
};
};
const AdminPage = connect(
mapStateToProps,
mapDispatchToProps
)(ConnectedAdminPage);
export default AdminPage;
The goal is to define 2 table rows fragments. Both rows will be loaded in the previous html table. The second row has a conditional display.
import * as React from "react";
import { confirmAlert } from "react-confirm-alert";
import "react-confirm-alert/src/react-confirm-alert.css";
import CSSModules from "react-css-modules";
import { connect } from "react-redux";
import { Button, Dropdown, Icon, Loader, Menu, Table } from "semantic-ui-react";
import { repsActions } from "../../_actions";
import { adminConstants, servicesConstants } from "../../_constants";
import { history } from "../../_helpers";
import HealthCheckPage from "../../HealthCheckPage";
import AdminTableMenu from "../AdminTableMenu";
import { GreenLed, RedLed, YellowLed } from "../Leds";
const styles = require("./AdminPageTable.less");
const options = {
allowMultiple: true
};
interface SelectedHealthCheck {
name: string;
index: number;
display: boolean;
}
interface Rep {
apiLink: string;
name: string;
description: string;
displayName: string;
healthStatus: string;
locations: any;
v4name: string;
status: string;
disabled: boolean;
version: string;
}
interface AdminPageTableProps {
rep: Rep;
displayHealthCheck: SelectedHealthCheck;
handleCellClick: (name: string, index: number) => any;
index: number;
getMicroServiceHealth: (name: string) => any;
repsConfig: any;
}
@CSSModules(styles, options)
export class AdminPageTable extends React.Component<AdminPageTableProps, any> {
public render() {
const {
rep,
displayHealthCheck,
handleCellClick,
index,
repsConfig,
repsConfig: { currentHealth = { status: adminConstants.DOWN } }
} = this.props;
return (
<React.Fragment>
<Table.Row textAlign="left">
<Table.Cell
width={1}
collapsing
selectable
onClick={() => handleCellClick(rep.name, index)}
>
<Icon link name="caret square down outline" size="large" />
</Table.Cell>
<Table.Cell
width={3}
selectable
onClick={() => handleCellClick(rep.name, index)}
>
{rep.name}
</Table.Cell>
<Table.Cell width={3}>{rep.v4name}</Table.Cell>
<Table.Cell width={3}>
{rep.disabled ? <RedLed /> : <GreenLed />}
</Table.Cell>
<Table.Cell width={3}>{rep.version}</Table.Cell>
<Table.Cell>
{repsConfig.loading ? (
<Loader active inline />
) : rep.healthStatus === adminConstants.UP ? (
<GreenLed />
) : rep.healthStatus === adminConstants.DOWN ? (
<RedLed />
) : rep.healthStatus === adminConstants.DEGRADED ? (
<YellowLed />
) : (
<RedLed />
)}
</Table.Cell>
<Table.Cell width={1}>
<AdminTableMenu rowprops={rep} />
</Table.Cell>
</Table.Row>
{displayHealthCheck.display && displayHealthCheck.index === index ? (
<Table.Row textAlign="left">
<Table.Cell width={1} />
<Table.Cell colSpan="5">
<HealthCheckPage microservice={displayHealthCheck.name} />
</Table.Cell>
</Table.Row>
) : null}
</React.Fragment>
);
}
}
function mapDispatchToProps(dispatch) {
return {
getMicroServiceHealth: name => {
dispatch(repsActions.getMicroServiceHealth(name));
}
};
}
const mapStateToProps = state => {
return {
repsConfig: state.repsConfig
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(AdminPageTable);
Thank you for sharing your thoughts and knowledge on this topic.
ReplyDeleteMern stack online training
Mern stack training in hyderabad
Do you have the code for the HealthCheck page? This stuff is really useful.
ReplyDelete