0

Inside my ReactJs SPFx web part i want to build a table as follow:-

<table style="width:100%">

  <tr>
    <td rowspan="2"></td>
    <td></td>
  </tr>
  <tr>
    <td></td>
  </tr>
</table>

i tried this code which will build a <td> inside the map iteration (currently i have 3 items to map), but it raised syntax errors mainly that the <tr> does not have a matching end tag:-

import * as React from 'react';
import { Icon } from 'office-ui-fabric-react/lib/Icon';

import styles from './SingleNews.module.scss';
import { ISingleNewsProps } from './ISingleNewsProps';

export interface INews {
    recentNews: ISingleNewsProps[];
    featuredNews?: ISingleNewsProps[];
    featured: boolean;
}

export default class SingleNews extends React.Component<INews, {}> {
    public render(): React.ReactElement<INews> {
        return (
            <><table>
                {this.props.featured
                    ? this.props.recentNews.map((post,index) => {
{index === 0 ? 
<tr>
<td rowSpan={2}>
<a
    className={styles.singleNews}
    href={post.link}
    key={post.Title}
>
    <div
        className={styles.singleNews__image}
        style={{ backgroundImage: `url(${post.image})` }}
    />
    <div className={styles.singleNews__content}>
        <div className={styles.singleNews__content__info}>
            <span className={styles.singleNews__content__info__label}>{post.Featured}</span>
            <span className={styles.singleNews__content__info__date}>
                {post.date}
            </span></div>
    </div>
    <div className={styles.singleNews__content}>
        <div className={styles.singleNews__content__info}>

            <h2 className={styles.singleNews__content__info__title}>
                {post.Title}
            </h2>



            {post.likes ? (
                <div
                    className={styles.singleNews__content__info__reactions}
                >
                    <span
                        className={
                            styles.singleNews__content__info__reactions__likes
                        }
                    >
                        <Icon iconName='Like' />
                        {post.likes}
                    </span>
                    <span>
                        <Icon iconName='ActionCenter' />
                        {post.coments}
                    </span>
                </div>
            ) : null}
        </div>
    </div>
</a></td> : null }

{index === 1 ? 

    <td >
    <a
        className={styles.singleNews}
        href={post.link}
        key={post.Title}
    >
        <div
            className={styles.singleNews__image}
            style={{ backgroundImage: `url(${post.image})` }}
        />
        <div className={styles.singleNews__content}>
            <div className={styles.singleNews__content__info}>
                <span className={styles.singleNews__content__info__label}>{post.Featured}</span>
                <span className={styles.singleNews__content__info__date}>
                    {post.date}
                </span></div>
        </div>
        <div className={styles.singleNews__content}>
            <div className={styles.singleNews__content__info}>
    
                <h2 className={styles.singleNews__content__info__title}>
                    {post.Title}
                </h2>
    
    
    
                {post.likes ? (
                    <div
                        className={styles.singleNews__content__info__reactions}
                    >
                        <span
                            className={
                                styles.singleNews__content__info__reactions__likes
                            }
                        >
                            <Icon iconName='Like' />
                            {post.likes}
                        </span>
                        <span>
                            <Icon iconName='ActionCenter' />
                            {post.coments}
                        </span>
                    </div>
                ) : null}
            </div>
        </div>
    </a></td></tr> : null }
    {index === 2 ? 
        <tr>
        <td >
        <a
            className={styles.singleNews}
            href={post.link}
            key={post.Title}
        >
            <div
                className={styles.singleNews__image}
                style={{ backgroundImage: `url(${post.image})` }}
            />
            <div className={styles.singleNews__content}>
                <div className={styles.singleNews__content__info}>
                    <span className={styles.singleNews__content__info__label}>{post.Featured}</span>
                    <span className={styles.singleNews__content__info__date}>
                        {post.date}
                    </span></div>
            </div>
            <div className={styles.singleNews__content}>
                <div className={styles.singleNews__content__info}>
        
                    <h2 className={styles.singleNews__content__info__title}>
                        {post.Title}
                    </h2>
        
        
        
                    {post.likes ? (
                        <div
                            className={styles.singleNews__content__info__reactions}
                        >
                            <span
                                className={
                                    styles.singleNews__content__info__reactions__likes
                                }
                            >
                                <Icon iconName='Like' />
                                {post.likes}
                            </span>
                            <span>
                                <Icon iconName='ActionCenter' />
                                {post.coments}
                            </span>
                        </div>
                    ) : null}
                </div>
            </div>
        </a></td></tr> : null }                 
                    })
                    
                                : null
                      }
            </table></>
        );
    }
}

Any advice ?

Thanks

2

First, considering each of those long, complicated <td> sections is the same, I would pull all of that out and make it its own component where you pass in the individual post and the rowspan (could be 1 or 2) as props:

NewsTableCell.tsx

import * as React from 'react';
import { Icon } from 'office-ui-fabric-react/lib/Icon';
import styles from './SingleNews.module.scss';
import { ISingleNewsProps } from './ISingleNewsProps';

export interface INewsTableCellProps {
    post: ISingleNewsProps;
    rowspan: number;
}

export default class NewsTableCell extends React.Component<INewsTableCellProps, {}> {
    public render(): React.ReactElement<INewsTableCellProps> {
        
        const { post, rowspan } = this.props;

        return (
            <td rowSpan={rowspan}>
                <a
                    className={styles.singleNews}
                    href={post.link}
                    key={post.Title}
                >
                    <div
                        className={styles.singleNews__image}
                        style={{ backgroundImage: `url(${post.image})` }}
                    />
                    <div className={styles.singleNews__content}>
                        <div className={styles.singleNews__content__info}>
                            <span className={styles.singleNews__content__info__label}>{post.Featured}</span>
                            <span className={styles.singleNews__content__info__date}>
                                {post.date}
                            </span>
                        </div>
                    </div>
                    <div className={styles.singleNews__content}>
                        <div className={styles.singleNews__content__info}>
                            <h2 className={styles.singleNews__content__info__title}>
                                {post.Title}
                            </h2>
                            {post.likes ? (
                                <div
                                    className={styles.singleNews__content__info__reactions}
                                >
                                    <span
                                        className={
                                            styles.singleNews__content__info__reactions__likes
                                        }
                                    >
                                        <Icon iconName='Like' />
                                        {post.likes}
                                    </span>
                                    <span>
                                        <Icon iconName='ActionCenter' />
                                        {post.coments}
                                    </span>
                                </div>
                            ) : null}
                        </div>
                    </div>
                </a>
            </td>
        );
    }
}

Then, in your other component, when you build the table, don't try and map over the posts in the return part, map over them before the return build an array of the new td / NewsTableCell components, and use that array in the return part:

import * as React from 'react';
import styles from './SingleNews.module.scss';
import { ISingleNewsProps } from './ISingleNewsProps';
import NewsTableCell from './NewsTableCell';

export interface INews {
    recentNews: ISingleNewsProps[];
    featuredNews?: ISingleNewsProps[];
    featured: boolean;
}

export default class SingleNews extends React.Component<INews, {}> {
    public render(): React.ReactElement<INews> {

        const newsTableCells = this.props.recentNews.map((post, index) => {
            return (
                <NewsTableCell
                    post={post}
                    rowspan={index === 0 ? 2 : 1}
                />
            );
        });

        return (
            <table>
                {this.props.featured ?
                    <>
                        <tr>
                            { newsTableCells[0] }
                            { newsTableCells[1] }
                        </tr>
                        <tr>
                            { newsTableCells[2] }
                        </tr>
                    </>
                    : null
                }
            </table>
        );
    }
}

That's going to keep your code much cleaner and easier to understand, and you won't run into the issue you're having where you have to break the HTML structure of the trs in your loop causing the error you're having.

1
  • thanks a lot .. your code worked perfectly for me..
    – john Gu
    Nov 26 '21 at 22:50

Not the answer you're looking for? Browse other questions tagged or ask your own question.