0

I've gone through all of the example questions on this and can't seem to figure out what my problem is.

Here is the full error:

index.js:1375 Warning: validateDOMNesting(...): Text nodes cannot appear as a child of <tbody>.
    in tbody (created by TableBody)
    in TableBody (at Favorites.js:167)
    in table (created by Table)
    in Table (at Favorites.js:123)
    in Favorites (created by ConnectFunction)
    in ConnectFunction (at App.js:73)
    in Route (at App.js:69)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:46)
    in div (created by Container)
    in Container (at App.js:44)
    in App (created by ConnectFunction)
    in ConnectFunction (at src/index.js:10)
    in Provider (at src/index.js:9)

and my full code

import React, { useState, useEffect } from "react";
import Search from "./Search";
import { connect } from "react-redux";
import {
  Table,
  Popup,
  Responsive,
  Button,
  Segment,
  Header,
  Image
} from "semantic-ui-react";
import { searchChange } from "../reducers/searchReducer";
import { fetchData } from "../reducers/baseballReducer";
import { removeFavorite } from "../reducers/favoriteReducer";
import { getFavorites } from "../reducers/favoriteReducer";
import { getUpdates } from "../reducers/updateReducer";
import { setNotification } from "../reducers/notificationReducer";
import _ from "lodash";
var moment = require("moment");
moment().format();

//Filter 'favupdates' state for user's input
const searchCards = ({ favUpdates, search }) => {
  return search
    ? favUpdates.filter(a =>
        a.title
          .toString()
          .toLowerCase()
          .includes(search.toLowerCase())
      )
    : favUpdates;
};

const style = {
  borderRadius: 0,
  padding: "2em"
};

const Favorites = props => {
  useEffect(() => {
    document.title = "My Favorites | All Vintage Search";
  }, []);

  useEffect(() => {
    props.getFavorites(props.loggedUser.id);
  }, [props.loggedUser]);

  //Set 'filteredData' state
  useEffect(() => {
    setData(props.cardsToShow);
  }, [props]);

  const mapFAVS = props.favorites;
  const data = Array.from(mapFAVS);
  const updatedFavs = data.map(item => item.id);
  const formatFavs = updatedFavs.map(id => id.join(","));
  console.log("FORMAT FAVS", formatFavs);

  //Get updated data from eBay based on user's favorite id's and update 'favUpdates' state
  useEffect(() => {
    props.getUpdates(formatFavs);
  }, [props.favorites]);

  const [column, setColumn] = useState(null);
  const [direction, setDirection] = useState(null);
  const [filteredData, setData] = useState(props.cardsToShow);

  console.log("Filtered Data", filteredData);

  const handleSortNumeric = clickedColumn => {
    const sorter = data => parseInt(data[clickedColumn]);
    setData(_.sortBy(filteredData, sorter));
  };

  const handleSortReverse = () => {
    const sorter = data => parseInt(data);
    setData(_.sortBy(filteredData, sorter).reverse());
  };

  const handleSort = clickedColumn => {
    if (column !== clickedColumn) {
      setColumn(clickedColumn);
      if (clickedColumn === "title" || "acceptsOffers" || "timeStamp") {
        setData(_.sortBy(filteredData, [clickedColumn]));
      } else {
        handleSortNumeric(clickedColumn);
      }
      setDirection("ascending");
      return;
    }

    if (clickedColumn === "title") {
      setData(_.sortBy(filteredData.reverse()));
    } else {
      handleSortReverse();
    }

    direction === "ascending"
      ? setDirection("descending")
      : setDirection("ascending");
  };

  const removeFavorite = card => {
    props.removeFavorite(card, props.loggedUser);
    props.setNotification(`You removed ${card.title}!`, 5);
  };

  if (!props.cardsToShow) return null;

  return (
    <>
      <Search />
      <Segment inverted color="blue">
        <Header inverted color="grey" size="medium">
          My Favorites
        </Header>
      </Segment>
      <Segment>Count: {props.cardsToShow.length}</Segment>
      <Responsive maxWidth={767}>
        <strong>Click to Sort:</strong>
      </Responsive>
      <Table sortable celled fixed striped>
        <Table.Header>
          <Table.Row>
            <Table.HeaderCell
              textAlign="center"
              sorted={column === "title" ? direction : null}
              onClick={() => handleSort("title")}
            >
              Card Title
            </Table.HeaderCell>
            <Table.HeaderCell
              width={2}
              textAlign="center"
              sorted={column === "updatedBids" ? direction : null}
              onClick={() => handleSort("updatedBids")}
            >
              # Bids
            </Table.HeaderCell>
            <Table.HeaderCell
              textAlign="center"
              sorted={column === "updatedPrice" ? direction : null}
              onClick={() => handleSort("updatedPrice")}
            >
              Price
            </Table.HeaderCell>
            <Table.HeaderCell
              textAlign="center"
              sorted={column === "timeStamp" ? direction : null}
              onClick={() => handleSort("timeStamp")}
            >
              Time Left
            </Table.HeaderCell>
            <Table.HeaderCell
              textAlign="center"
              sorted={column === "status" ? direction : null}
              onClick={() => handleSort("status")}
            >
              Status
            </Table.HeaderCell>
            <Table.HeaderCell textAlign="center" width={2}>
              Remove
            </Table.HeaderCell>
          </Table.Row>
        </Table.Header>
        <Table.Body>
          {!filteredData
            ? "Sorry No Cards Found"
            : filteredData.map(card => (
                <>
                  <Responsive maxWidth={767}>
                        <div className="ui piled compact segment">
                          <div className="ui card">
                            <div className="blurring dimmable image">
                              <div className="ui inverted dimmer">
                                <div className="content">
                                  <div className="center">
                                    <div className="ui red button view">
                                      VIEW
                                    </div>
                                  </div>
                                </div>
                              </div>
                              <Image
                                src={card.image}
                                href={card.itemURL}
                                centered
                                style={{ padding: "5px" }}
                              />
                            </div>
                            <div className="content">
                              <div
                                id="rate"
                                className="ui star rating right floated"
                                data-rating="3"
                              ></div>
                              <div className="header">
                                <a href={card.itemURL}>{card.title}</a>
                              </div>
                              <div
                                className="meta"
                                style={{ padding: "5px 0 0 0" }}
                              >
                                <span className="date">
                                  <i className="clock icon"></i> Ends in{" "}
                                  {moment
                                    .duration(card.timeLeft, "minutes")
                                    .humanize()}
                                </span>
                                <div style={{ padding: "10px 0 0 0" }}>
                                  <span>
                                    <Button color="green">
                                      ${card.updatedPrice}
                                    </Button>
                                  </span>
                                  <span class="right floated date">
                                    {" "}
                                    <Button
                                      onClick={() => removeFavorite(card)}
                                      color="red"
                                      icon="remove circle"
                                    />
                                  </span>
                                </div>
                              </div>
                            </div>
                            <div className="extra content">
                              <div
                                className="ui right labeled button"
                                data-content="Bids"
                                data-variation="tiny"
                                tabindex="0"
                              >
                                <div className="ui blue icon tiny button">
                                  <i className="gavel large icon"></i>
                                </div>
                                <a
                                  href={card.itemURL}
                                  className="ui basic blue left pointing label"
                                >
                                  {card.updatedBids}
                                </a>
                              </div>
                              <div
                                className="ui left labeled right floated button"
                                data-content="Watch Count"
                                data-variation="tiny"
                                tabindex="0"
                              >
                                <a
                                  href={card.itemURL}
                                  className="ui basic blue right pointing label"
                                >
                                  {card.status}
                                </a>
                                <div className="ui blue icon tiny button">
                                  <i className="history large icon"></i>
                                </div>
                              </div>
                            </div>
                          </div>
                        </div>
                  </Responsive>
                  <Responsive
                    as={"tr"}
                    minWidth={768}
                    style={{ width: "100%" }}
                  >
                    <Popup
                      trigger={
                        <Table.Cell>
                          <a href={card.itemURL} target={"_blank"}>
                            {card.title}
                          </a>
                        </Table.Cell>
                      }
                      content={
                        <img
                          alt={card.title}
                          src={card.image}
                          height="250"
                        ></img>
                      }
                      style={style}
                      size="small"
                      position="left center"
                    ></Popup>
                    <Table.Cell textAlign="center">
                      {card.updatedBids}
                    </Table.Cell>
                    <Table.Cell textAlign="center">
                      ${card.updatedPrice}
                    </Table.Cell>
                    <Table.Cell textAlign="center">
                      {moment.duration(card.timeLeft, "minutes").humanize()}
                    </Table.Cell>
                    <Table.Cell textAlign="center">{card.status}</Table.Cell>
                    <Table.Cell textAlign="center">
                      <Button
                        onClick={() => removeFavorite(card)}
                        color="red"
                        icon="remove circle"
                      />
                    </Table.Cell>
                  </Responsive>
                </>
              ))}
        </Table.Body>
        <Table.Footer>
          <Table.Row>
            <Table.HeaderCell colSpan="6"></Table.HeaderCell>
          </Table.Row>
        </Table.Footer>
      </Table>
    </>
  );
};

const mapStateToProps = state => {
  return {
    baseball: state.baseball,
    favorites: state.favorites,
    favUpdates: state.favUpdates,
    loggedUser: state.loggedUser,
    page: state.page,
    entries: state.entries,
    query: state.query,
    pageOutput: state.pageOutput,
    search: state.search,
    cardsToShow: searchCards(state)
  };
};

const mapDispatchToProps = {
  searchChange,
  fetchData,
  removeFavorite,
  getFavorites,
  getUpdates,
  setNotification
};

export default connect(mapStateToProps, mapDispatchToProps)(Favorites);

I suspected the issue might be where i'm using the section as I dont have any table rows or cells set within the Table Body. I tried wrapping that whole section with a Table.Row and a Table.Cell, but still getting the same error. Any ideas?

1 Answer 1

2

If !filteredData === false then the only child of <Table.Body> is text.

As the error says, the table body cannot have text as a child.

Wrap the text like this <Table.Row><Table.Cell>Sorry no cards shown</Table.Cell></Table.Row>

Sign up to request clarification or add additional context in comments.

2 Comments

thanks! after i fix that i get a <div> cannot appear as a child of <tbody>, which is sort of what i thought was issue at first---any ideas on that?
If <Responsive> renders with an outer component of a <div>, then that would explain the error. Try wrapping that in a <Table.Row> and <Table.Cell> like you did for the text, based on what you need. I believe when you create a cell, if it needs to take the entire row width, you will need to set the column length of it to the number of columns. Not sure of the exact syntax.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.