简体   繁体   中英

Unable to render HTML UL conditionally in Reactjs

I am trying to render a list not more than 5 conditionally by checking the number of items and a "more" button. When I pass in 5 li items it renders it as text instead of HTML elements.

let sectionCount = 0;
const MAX_COUNT_TO_SHOW = 5;
const getAssets = data => {
  let assets = "<ul>";
  let index = 0;
  for (var improperAsset of data) {
    if (index < MAX_COUNT_TO_SHOW) {
      assets += "<li>" + improperAsset + "</li>";
    }
    index++;
  }
  assets += "</ul>";
  console.log(assets);
  return <div>{assets}</div>;
};
const getSectionBody = info => {
  if (info.ic > MAX_COUNT_TO_SHOW) {
    return (
      <div>
        <p>
          {info.name} should be named as <b>{info.label}</b>
        </p>
        <i>
          <b>{info.ic}</b> instance(s) located for improper naming
        </i>
        {getAssets(info.data)}
        <div style={{ color: "blue" }} onClick={() => openDialog(info["data"])}>
          Show More
        </div>
      </div>
    );
  } else {
    return (
      <div>
        <p>
          {info.name} should be named as <b>{info.label}</b>
        </p>
        <i>
          <b>{info.ic}</b> instance(s) located for improper naming
        </i>
        {getAssets(info.data)}
      </div>
    );
  }
};

const isCollapsible = () => {
  if (sectionCount == 0) {
    sectionCount++;
    return true;
  } else {
    return false;
  }
};

const openDialog = useCallback(
  data => {
    setAssetsInfo(data);
    setClosed(false);
  },
  [setClosed]
);

return (
  <div style={{ margin: "0px 0px 10px 10px" }}>
    <Container fluid style={{ padding: "0px" }}>
      <Row>
        <Col sm={3}>
          <Button variant="primary">Customize</Button>
        </Col>
      </Row>
    </Container>
    <Panel title={""}>
      {myData.map(info => {
        return (
          <Section
            key={uuid()}
            title={info.name + " " + info.tc + " (" + info.ic + ")"}
            collapsible
            expanded={isCollapsible()}
            initialCollapsed={true}
          >
            <Container fluid={true}>{getSectionBody(info)}</Container>
          </Section>
        );
      })}

      <MainDialog
        assetsInfo={assetsInfo}
        closed={closed}
        setClosed={setClosed}
      ></MainDialog>
    </Panel>
  </div>
);

在此处输入图像描述

It is because you are passing in the data as a string rather than actual JSX elements. While you CAN do this it is very close to never being a good idea.

There are many ways to skin a cat but consider something like the following

const getAssets = data => {
  return 
    (
        <div>
            <ul>
              {data.slice(0,5).map((improperAsset) => (<li>{improperAsset}</li>))}
            </ul>
        </div>
    );
};

If your "improperAsset" contains html and needs to be rendered as such, I would consider either moving these improper assets into separate components or using a library to handle HTML parsing otherwise you run serious risk of introducing cross site scripting vulnerabilities into your site.

FYI, that's how the minimal reproducible example may look like in that case. If you want to do that this way you can use dangerouslySetInnerHTML but as mentioned earlier, this may expose your code to cross-site scripting .

return <div dangerouslySetInnerHTML={{ __html: assets }}></div>;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM