In my jsx file I have the following function:
function GetComments({commentsArray}) {
return commentsArray.map((comment) => {
let localId = comment.LocalId;
return (
<div className="comments-container">
<div className="commenter">
<span className="id-label">{comment.LocalId}</span>
<script>
if (comment.ParentCommentId !== null) {
document.write("<span class=reply title=in reply to " comment.LocalId "></span>")
}
</script>
</div>
</div>
);
});
}
Now I don't get any errors but when that script tag part is in there, the page just doesn't load, it's just constantly stuck trying to load. Where have I gone wrong with adding a script to this? I am only wanting that element created when that condition is met. I have been looking online and I see that it's different in jsx for adding scripts but confused on how to correctly implement my script
CodePudding user response:
I have managed to actually come up with a way to solve the issue, don't know if this is the best way.
I created an additional function where I pass the id into it and do the check there.
function ParentIdCheck({id}) {
if (id !== null) {
return(
<span className="reply" title={"in reply to " id}></span>
);
}
}
and now the original function looks like:
function GetComments({commentsArray}) {
return commentsArray.map((comment) => {
let localId = comment.LocalId;
return (
<div className="comments-container">
<div className="commenter">
<span className="id-label">{comment.LocalId}</span>
<ParentIdCheck id = {comment.ParentCommentId}/>
</div>
</div>
);
});
}
I don't know if this is the best way though, so open to suggestions on how to improve this
CodePudding user response:
There are a few problems with your code, the biggest of which is the use of document.write
, which you should never be using in react code. To understand why, it's important to realize that one of the most fundamental design goals of react is to abstract any direct manipulation of the DOM away from the user and instead allow them to specify the way in which a lighter weight virtual DOM reacts to state changes. Try something like the following:
export function GetComments({ commentsArray }) {
return (
<>
{commentsArray.map((comment) => {
const localId = comment.LocalId;
return (
<div key={localId} className="comments-container">
<div className="commenter">
<span className="id-label">{localId}</span>
{comment.ParentCommentId && (
<span className="reply" title={`in reply to ${localId}`} />
)}
</div>
</div>
);
})}
</>
);
}
In addition to doing away with document.write
, this addresses the following issues:
- Consistent use of
localId
. - Conditional rendering to render the
"reply"
span
whencomment.ParentCommentId
is truthy. - Template literals to more clearly express the "in reply to" string. This is maybe a bit more of a style issue than a functional one, but template literals are the modern way to format variables into string templates.
- The use of key inside the map to "help React identify which items have changed, are added, or are removed."
- Wrapping the whole
map
expression in a fragment so that it has a return type which is not an array, which is a requirement for it being used as a JSX element.