I have an object of data I am pulling through from a CMS to create a blog and am mapping through the content object in order to render out the main body of the blog.
I have created a ternary operator to essentially say, that if the line of text has a type of 'strong', make the font bold, otherwise if it has a type of 'hyperlink', make the piece of text a link within an tag.
The issue I'm having is that some pieces of text are both 'bold' and 'hyperlinks', and so it is rendering out the sentence twice, how can I ensure that when the type is both 'bold' & 'hyperlink', it only renders once?
This is what my data looks like:
and here is my file where I return this data on the frontend:
<div className='text-left mt-12 text-white'>
<h1 className='text-5xl mb-4 font-header text-blue-500'>
{RichText.asText(data.title)}
</h1>
{data.content.map((t, i) => {
return (
<>
{!t.spans[0] && (
<p className={`text-lg mt-6 opacity-80 ${t.type}`}>
{t.text}
</p>
)}
{t.spans.map((item) =>
item.type === 'strong' ? (
<p className={`text-xl mt-6 font-bold ${t.type}`}>
{t.text}
</p>
) : item.type === 'hyperlink' ? (
<a
href={item.data.url}
target='_blank'
className={`text-lg opacity-80 mt-6 text-blue-500 ${t.type}`}>
{t.text}
</a>
) : item.type === 'list-item' ? (
<ul className='list-disc'>
<li className='text-lg mt-4 text-white'>{t.text}</li>
</ul>
) : (
<p
className={`text-lg opacity-80 mt-6 font-bold ${t.type}`}>
{t.text}
</p>
)
)}
</>
);
})}
</div>
I'm sure this is simple but I wondered the best way to handle something like this?
Thanks in advance!
CodePudding user response:
Don't make your logic switching cases on type.
Try something like this:
const styleProps = spans.reduce((acc, span) => {
if (span === 'strong'){
acc['font-weight'] = 'bold';
}
if (span === 'something-else'){
acc['some-css-prop'] = 'some-value';
}
...
return acc;
}, {})
and then you will have an accumulator (styleProps
) with all the necessary props needed to style your component.
<YourComponent className="my-constant-class-name" style={{...styleProps}} />
You can generalize this idea:
ex.
const MyComponentProps = spans.reduce((acc, span) => {
if (span === 'strong'){
acc.style['font-weight'] = 'bold';
}
if (span === 'hyperlink'){
acc['href'] = 'www.example.com';
}
...
return acc;
}, {});
and also
let MyComponent = null;
switch(type){
case 'hyperlink':
MyComponent = (props) => <a {...props} />;
break;
case 'text':
MyComponent = (props) => <p {...props} />;
break;
case 'bullet':
MyComponent = (props) => <li {...props} />;
break;
and then
<MyComponent {...MyComponentProps} />