React项目中如何在CompareDialog.js实现诊所营业时间换行展示
Got it, let's figure out how to fix that line break issue in your CompareDialog.js. The core problem here is that when you convert the opening hours into a plain string, JSX doesn't render newline characters (\n) as actual line breaks by default, and relying on dangerouslySetInnerHTML can be unnecessary (or even risky if you're dealing with untrusted data). Let's walk through the best approaches to match the line-separated output you have in GpDialog.js.
1. Reuse JSX Rendering Logic (Cleanest Approach)
Since you already have a working JSX implementation in GpDialog.js, the simplest fix is to avoid converting the opening hours to a string entirely. Instead, pass a list of JSX elements from ClinicMap.js to CompareDialog.js.
Step 1: Update ClinicMap.js to generate JSX instead of a string
Replace your code that creates formattedOpeningHours as a string with this logic that builds a JSX array:
// In ClinicMap.js, when processing the clinic data const formatOpeningHours = (hoursData) => { return hoursData.map((hourGroup, index) => ( <div key={index} className="clinic-hour-group"> <strong>{hourGroup.day_string}</strong> <div className="hours-list"> {hourGroup.opening_hours.map((hour, hourIndex) => ( <span key={hourIndex}>{hour}</span> ))} </div> </div> )); }; // Then assign it to formattedOpeningHours const formattedOpeningHours = formatOpeningHours(clinic.properties.ALL_OPENING_HOURS);
Step 2: Render the JSX directly in CompareDialog.js
Instead of treating formattedOpeningHours as a string, just render it as a React element:
// In CompareDialog.js return ( <div className="compare-dialog"> {/* Other content */} <div className="clinic-opening-hours"> {formattedOpeningHours} </div> </div> );
Add some basic CSS to style the groups and hours:
.clinic-hour-group { margin-bottom: 0.5rem; } .hours-list span { display: block; /* Makes each hour slot a new line */ margin-left: 0.5rem; }
2. Fix the String-Based Approach (If You Need to Keep Strings)
If you have to keep formattedOpeningHours as a string (for example, due to existing data flow), use one of these safe methods to get line breaks:
Option A: Use CSS to Preserve Newlines
Add this CSS class to the container holding the opening hours string:
.opening-hours-string-container { white-space: pre-wrap; }
Then render the string in this container:
<div className="opening-hours-string-container"> {formattedOpeningHours} </div>
This tells the browser to respect newline characters (\n) in the string and render them as line breaks.
Option B: Split the String into Lines and Render as JSX
Split the string by newline characters and map each line to a paragraph or span element:
// In CompareDialog.js const hourLines = formattedOpeningHours.split('\n').filter(line => line.trim() !== ''); // Remove empty lines return ( <div className="opening-hours"> {hourLines.map((line, index) => ( <p key={index} className="hour-line">{line}</p> ))} </div> );
Option C: Safe Use of dangerouslySetInnerHTML (Only if Necessary)
If your string includes <br> tags instead of newlines, you can use this method—but only if you're 100% sure the string doesn't contain untrusted user input (to avoid XSS risks):
<div dangerouslySetInnerHTML={{ __html: formattedOpeningHours }} />
3. Why Your Previous Attempts Didn't Work
- Newline characters (
\n) in plain strings are ignored by JSX because it renders text in inline contexts by default. - If you used
dangerouslySetInnerHTMLbut it didn't work, you probably forgot to replace newlines with<br>tags first (e.g.,formattedOpeningHours.replace(/\n/g, '<br>')). But again, the JSX approach is safer and cleaner.
内容的提问来源于stack exchange,提问作者Prashin Jeevaganth

