Here's one way of doing it: Utilizing React Fragment.
working example: https://codesandbox.io/s/92r12m7zp
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<pattern id="pattern" x="0" y="0" width="24" height="24" patternUnits="userSpaceOnUse">
<rect fill="rgba(159, 188, 191, 0.15)" x="0" width="20" height="20" y="0" />
<rect fill="rgba(159, 188, 191, 0.15)" x="20" width="20" height="20" y="20" />
</pattern>
<rect fill="url(#pattern)" x="0" y="0" width="100%" height="100%" />
</svg>
<div id="accordion"></div>
</body>
</html>
index.js
import React from "react";
import { render } from "react-dom";
import Accordian from "./Accordian";
import "./styles.css";
render(<Accordian />, document.getElementById("accordion"));
Accordian.js
import map from "lodash/map";
import React, { Component } from "react";
import AccordionItem from "./AccordianItem";
import SampleQuestions from "./sampleQuestions";
export default class Accordion extends Component {
state = { questions: SampleQuestions };
render = () => (
<div className="mainbody">
<h1>What is...</h1>
<div className="accordion-container">
{map(this.state.questions, ({ key, ...rest }) => (
<AccordionItem key={key} {...rest} />
))}
</div>
</div>
);
}
AccordianItem.js
import React, { Component } from "react";
export default class AccordionItem extends Component {
state = { isActive: false };
toggle = () => this.setState(prevState => ({ isActive: !this.state.isActive }));
render = () => (
<div
className={`${this.state.isActive ? "active" : "inactive"}`}
onClick={this.toggle}
>
<span className="summary">> {this.props.summary}</span>
<span className="folding-pannel answer">
{this.props.answer}
</span>
</div>
);
}
sampleQuestions.js
import React, { Fragment } from "react";
const Link = url => (
<a href={url} target="_blank">
here
</a>
);
export default [
{
key: "capital-of-canada",
summary: "the capital of Canada?",
answer: (
<Fragment>
Ottawa baby!! Click {Link("https://en.wikipedia.org/wiki/Ottawa")} for
more details
</Fragment>
)
},
{
key: "whale-lifespan",
summary: "the life span of a bowhead whale?",
answer: "Over 200 years!!"
},
{
key: "most-popular-city",
summary: "the most visited city in the world?",
answer: "London, groovy baby!!"
},
{
key: "warmest-ocean",
summary: "the warmest ocean?",
answer: "Indian Ocean, it's a hottie!"
},
{
key: "swanson",
summary: "the one thing ron swanson hates more than lying?",
answer: "Skim milk, which is water that's lying about being milk"
}
];
Here's another way of doing it: Utilizing arrays with mixed content.
Working example: https://codesandbox.io/s/1v1xmq1kmq
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<pattern id="pattern" x="0" y="0" width="24" height="24" patternUnits="userSpaceOnUse">
<rect fill="rgba(159, 188, 191, 0.15)" x="0" width="20" height="20" y="0" />
<rect fill="rgba(159, 188, 191, 0.15)" x="20" width="20" height="20" y="20" />
</pattern>
<rect fill="url(#pattern)" x="0" y="0" width="100%" height="100%" />
</svg>
<div id="accordion"></div>
</body>
</html>
index.js
import React from "react";
import { render } from "react-dom";
import Accordian from "./Accordian";
import "./styles.css";
render(<Accordian />, document.getElementById("accordion"));
Accordian.js
import map from "lodash/map";
import React, { Component } from "react";
import AccordionItem from "./AccordianItem";
import SampleQuestions from "./sampleQuestions";
export default class Accordion extends Component {
state = { questions: SampleQuestions };
render = () => (
<div className="mainbody">
<h1>What is...</h1>
<div className="accordion-container">
{map(this.state.questions, ({ key, ...rest }) => (
<AccordionItem key={key} {...rest} />
))}
</div>
</div>
);
}
AccordianItem.js
import each from "lodash/each";
import React, { Component, Fragment } from "react";
import uuid from "uuid/v5";
export default class AccordionItem extends Component {
state = { isActive: false };
toggle = () => this.setState(prevState => ({ isActive: !this.state.isActive }));
render = () => (
<div
className={`${this.state.isActive ? "active" : "inactive"}`}
onClick={this.toggle}
>
<span className="summary">> {this.props.summary}</span>
<span className="folding-pannel answer">
{each(this.props.answer, prop => <Fragment key={uuid}>{prop}</Fragment>)}
</span>
</div>
);
}
sampleQuestions.js
import React from "react";
const Link = url => (
<a href={url} target="_blank">
here
</a>
);
export default [
{
key: "capital-of-canada",
summary: "the capital of Canada?",
answer: [
"Ottawa baby!! Click ",
Link("https://en.wikipedia.org/wiki/Ottawa"),
" for more details"
]
},
{
key: "whale-lifespan",
summary: "the life span of a bowhead whale?",
answer: ["Over 200 years!!"]
},
{
key: "most-popular-city",
summary: "the most visited city in the world?",
answer: ["London, groovy baby!!"]
},
{
key: "warmest-ocean",
summary: "the warmest ocean?",
answer: ["Indian Ocean, it's a hottie!"]
},
{
key: "swanson",
summary: "the one thing ron swanson hates more than lying?",
answer: ["Skim milk, which is water that's lying about being milk"]
}
];
Working example: https://codesandbox.io/s/0q1mv0omkw
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<pattern id="pattern" x="0" y="0" width="24" height="24" patternUnits="userSpaceOnUse">
<rect fill="rgba(159, 188, 191, 0.15)" x="0" width="20" height="20" y="0" />
<rect fill="rgba(159, 188, 191, 0.15)" x="20" width="20" height="20" y="20" />
</pattern>
<rect fill="url(#pattern)" x="0" y="0" width="100%" height="100%" />
</svg>
<div id="accordion"></div>
</body>
</html>
index.js
import React from "react";
import { render } from "react-dom";
import Accordian from "./Accordian";
import "./styles.css";
render(<Accordian />, document.getElementById("accordion"));
Accordian.js
import map from "lodash/map";
import React, { Component } from "react";
import AccordionItem from "./AccordianItem";
import SampleQuestions from "./sampleQuestions";
export default class Accordion extends Component {
state = { questions: SampleQuestions };
render = () => (
<div className="mainbody">
<h1>What is...</h1>
<div className="accordion-container">
{map(this.state.questions, ({ key, ...rest }) => (
<AccordionItem key={key} {...rest} />
))}
</div>
</div>
);
}
AccordianItem.js
import React, { Component } from "react";
import sanitizeHtml from "sanitize-html";
export default class AccordionItem extends Component {
state = { isActive: false };
toggle = () => this.setState(prevState => ({ isActive: !this.state.isActive }));
sanitize = ans =>
sanitizeHtml(ans, {
allowedTags: ["a"],
allowedAttributes: {
a: ["href", "target"]
}
});
render = () => (
<div
className={`${this.state.isActive ? "active" : "inactive"}`}
onClick={this.toggle}
>
<span className="summary">> {this.props.summary}</span>
<span
className="folding-pannel answer"
dangerouslySetInnerHTML={{
__html: this.sanitize(this.props.answer)
}}
/>
</div>
);
}
sampleQuestions.js
const Link = url => `<a href=${url} target="_blank">here</a>`;
export default [
{
key: "capital-of-canada",
summary: "the capital of Canada?",
answer: `Ottawa baby!! Click ${Link("https://en.wikipedia.org/wiki/Ottawa")} for more details`
},
{
key: "whale-lifespan",
summary: "the life span of a bowhead whale?",
answer: "Over 200 years!!"
},
{
key: "most-popular-city",
summary: "the most visited city in the world?",
answer: "London, groovy baby!!"
},
{
key: "warmest-ocean",
summary: "the warmest ocean?",
answer: "Indian Ocean, it's a hottie!"
},
{
key: "swanson",
summary: "the one thing ron swanson hates more than lying?",
answer: "Skim milk, which is water that's lying about being milk"
}
];