使用React spring的动画useTransition在递归循环中未按预期工作



我无法在我正在处理的注释部分中对div应用转换。注释部分是递归呈现的,每个注释部分都有一个useTransition实例。当点击对任何评论的回复按钮时,回复表单都应该转入。同样,当点击显示/隐藏评论时,它的所有子项都应该转出,但转换效果会应用于所有div。我做了一个代码笔来说明这个问题。请给我指正确的方向。非常感谢。

import React, { useState, useEffect } from "https://cdn.skypack.dev/react@17.0.1";
import * as ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";
import styled from "https://cdn.skypack.dev/styled-components@5.3.0";
import { useSpring, useTransition, animated } from "https://cdn.skypack.dev/react-spring@9.2.4";

/////////   Styled Components   ///////////////////////////////

const CommentDisplay = styled(animated.div)`
max-height: 100%;
margin: 10px 0px 0px 25px;
position: relative;

img {

width: 25px;
height: 25px;
margin: 1px 10px 0px 0px;
border-radius: 50%;
border: 1px solid gray;
}
`;


const TopBarWrapper = styled.div`
display: flex;
position: relative;
z-index: -1;
`;


const BorderDiv = styled.div`
position: absolute;
border-left: 1px solid gray;
height: calc(100% - 25px);
width: 100%;
margin-left: 12px;
bottom: 0px;
pointer-events: none;
`;


const CommentBody = styled.p`

overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-word;
padding-left: 35px;
`;


const BottomBarWrapper = styled.div`
grid-area: bottomBar;
display: flex;
flex-direction: row;
padding-left: 35px;
`;


const Reply = styled.div`

color: rgba(7, 7, 7, 0.65);
cursor: pointer;
padding: 8px 8px 8px 0px;
font-size: 14px;
&:hover{
color: black;
}
`;


const VoteUp = styled.div`

cursor: pointer;
padding: 8px;
&:hover{
background-color: #e5f4fb;
}
svg{
width: 16px;
height: 15px;
margin-right: 4px;
}
span{
font-size: 13px;
}
`;

const VoteDown = styled.div`

cursor: pointer;
padding: 8px;
&:hover{
background-color: #e5f4fb;
}
svg{
width: 16px;
height: 15px;
margin-right: 4px;
}
span{
font-size: 13px;
}
`;


const Form = styled.form`
display: grid;
//grid-template-columns: 90%;
grid-gap: 1.5rem;

grid-area: main_comment_body;
`;

const FormWrapper = styled.div`
display: ${props => props.rows[props.commentid] == "true" ? "grid" : "grid"};
grid-template-columns: minmax(min-content, max-content) 1fr;
grid-template-rows: minmax(50px, 1fr) minmax(min-content, max-content);
grid-template-areas:
"main_comment_img      main_comment_body  "
"main_comment_img     main_comment_buttons";

margin: 0px 50px 0px 85px;
z-index: ${props => props.rows[props.commentid] == "true" ? "1" : "-1"};
opacity: ${props => props.rows[props.commentid] == "true" ? "1" : "0"};
height: ${props => props.rows[props.commentid] == "true" ? "initial" : "0px"};
min-height: ${props => props.rows[props.commentid] == "true" ? "100px" : "0px"};

position: relative;
top: ${props => props.rows[props.commentid] == "true" ? "7px" : "-100px"};
left: 0;
background-color: F4F4F4;
transition: all .05s ease 0s;
img {
width: 25px;
height: 25px;
grid-area: avatar;
margin: 1px 10px 0px 0px;
border-radius: 50%;
border: 1px solid gray;

grid-Area: main_comment_img;

}
`;


const CommentSection = () => {



//in the useEffect hook, an ajax call gets all the comments from the rails server (in this case, it's a hard coded //"allComments" object below) and recursivley gets the id of every comment, reply, reply of reply etc.. and builds an //object in the format of {"comment id" : " false"}.  
//  
// example showMore initial state  
//   {"207":"false",
//   "208":"false",
//   "209":"false",
//   "210":"false",
//   "211":"false",
//   "212":"false",
//   "213":"false",
//   "214":"false"}
//  
//  when the "show/hide" comments button is clicked, it sets the id of all its children to "true" in the showMore state //variable, causing the css to //toggle it out of view. 

const [showMore, setShowMore] = useState({});
const [rows, setRows] = useState({});

// "rows" is identical to "showMore" but is used when the "reply" button in clicked, causing the reply form appear.



//response from server containing all the comments and its nested replies etc..
const allComments = [
{
"id": 295,
"body": "This is a First level comment to the main Story blah blah...",
"created_at": "2021-07-16T17:17:10.410Z",
"updated_at": "2021-07-16T17:17:10.410Z",
"original_comment_author": null,
"parent_id": null,
"ancestry": null,
"date": "less than a minute",
"comment_number": 256,
"reply": false,
"user_id": 1,
"commentable_type": "Story",
"commentable_id": 1,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "Jimmy",
"comments": [
{
"id": 296,
"body": "this is the first reply to the main comment ",
"created_at": "2021-07-16T17:17:49.585Z",
"updated_at": "2021-07-16T17:17:49.585Z",
"original_comment_author": "undefined",
"parent_id": 295,
"ancestry": "295",
"date": "less than a minute",
"comment_number": 257,
"reply": true,
"user_id": 1,
"commentable_type": "Comment",
"commentable_id": 295,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "izzy",
"comments": [
{
"id": 298,
"body": "Reply to the reply (3rd level)",
"created_at": "2021-07-16T17:22:46.088Z",
"updated_at": "2021-07-16T17:22:46.088Z",
"original_comment_author": "undefined",
"parent_id": 296,
"ancestry": "295/296",
"date": "less than a minute",
"comment_number": 259,
"reply": true,
"user_id": 1,
"commentable_type": "Comment",
"commentable_id": 296,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "Noel",
"comments": [
{
"id": 299,
"body": "another reply to a reply (4th level) etc...",
"created_at": "2021-07-16T17:23:10.561Z",
"updated_at": "2021-07-16T17:23:10.561Z",
"original_comment_author": "undefined",
"parent_id": 298,
"ancestry": "295/296/298",
"date": "less than a minute",
"comment_number": 260,
"reply": true,
"user_id": 1,
"commentable_type": "Comment",
"commentable_id": 298,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "Mitch",
"comments": []
}
]
}
]
},
{
"id": 297,
"body": "this is a second reply to the main comment .... ",
"created_at": "2021-07-16T17:18:59.249Z",
"updated_at": "2021-07-16T17:18:59.249Z",
"original_comment_author": "undefined",
"parent_id": 295,
"ancestry": "295",
"date": "less than a minute",
"comment_number": 258,
"reply": true,
"user_id": 1,
"commentable_type": "Comment",
"commentable_id": 295,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "mike",
"comments": []
}
]
},
{
"id": 294,
"body": "This is another First Level comment to the main story ... ",
"created_at": "2021-07-16T17:16:19.314Z",
"updated_at": "2021-07-16T17:16:19.314Z",
"original_comment_author": null,
"parent_id": null,
"ancestry": null,
"date": "less than a minute",
"comment_number": 255,
"reply": false,
"user_id": 1,
"commentable_type": "Story",
"commentable_id": 1,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "Natalie",
"comments": []
}
]
;


useEffect( () => {

addAllCommentsToStateForReplyButtonToWork(allComments)
addAllCommentsToStateForShowMoreButtonToWork(allComments)

},[]);


const getReplyArray = (childrenCommentArray) => {
let tempArray = []
childrenCommentArray.map( (x, i) => {
x.id
tempArray.push(x.id + ", ")
});
return tempArray.length > 0 ? tempArray : "blank"

};
function addAllCommentsToStateForReplyButtonToWork(c) {
let newArray = [];
let newState = {};
function getAllId(arr, key) {

arr.forEach(function(item) {
for (let keys in item) {
if (keys === key) {
newArray.push(item[key])
} else if (Array.isArray(item[keys])) {
getAllId(item[keys], key);
}
}
});
}
getAllId(c, 'id');
newArray.forEach(function(item) {
newState[item] = "false";
})
setRows(newState);
}  
function addAllCommentsToStateForShowMoreButtonToWork(c) {
let newArray = [];
let newState = {};
function getAllId(arr, key) {

arr.forEach(function(item) {
for (let keys in item) {
if (keys === key) {
newArray.push(item[key])
} else if (Array.isArray(item[keys])) {
getAllId(item[keys], key)
}
}
})
}
getAllId(c, 'id')
newArray.forEach(function(item) {
newState[item] = "false"
})
setShowMore(newState);
}

const handleSubmitClick = (e) => {

e.preventDefault()
}
const hideCommentsOrShowComments = (childrenCommentArray) => {


let tempArray = []
let numOfTrue = 0
let numOfFalse = 0
let tempShowMore = {}

childrenCommentArray.map( (x, i) => {
tempArray.push(x.id)
})

tempArray.forEach (x => {
if (showMore[x] == "true"){
numOfTrue = numOfTrue + 1
}else{

numOfFalse = numOfFalse + 1
}
})
if (numOfTrue > 0){
return "show replies"

}else{

return "hide replies"
}

}

const handleShowMoreButton = (childrenCommentArray) => {

//console.log("handleShowMoreButtonfrom article.jsx------------------------")


let tempArray = []
let tempShowMore = {}
childrenCommentArray.map( (x, i) => {



tempArray.push(x.id)




})


tempArray.forEach (x => {
//console.log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx idididid" + x)
if (showMore[x] == "true"){

//console.log("in if and x is = " + x + " and was true, changing it!")

tempShowMore[x] = "false"

}else{
//console.log("in else and x is = " + x + " and was false, changing it!")

tempShowMore[x] = "true"

}


} )
setShowMore({...showMore, ...tempShowMore})
}

const handleReplyButton = (id) => {

if (rows[id] == "true"){
setRows({...rows, [id]: "false"})
}else{
setRows({...rows,[id]: "true"})
}



}

const handleChange = () => {


//
}



////////////// Comment Function, Called recursively ///////////////
function Comment({ item, rows, showMore, handleShowMoreButton, handleReplyButton }){


const transition = useTransition(showMore[item.id], {

from: {opacity: 0},
enter: {y: 0, opacity: 1},
leave: {opacity: 0},
delay: 100

});


const nestedComments = (item.comments || []).map(com => {
return <Comment style={{border: "2px solid blue"}} key={com.id} item={com} type="child" rows={rows} 
showMore={showMore} handleShowMoreButton={handleShowMoreButton} 
handleReplyButton={handleReplyButton}/>
});

return (

<>
{transition((style,val) => val == "true" ? '' : 

<CommentDisplay 
style={style} 
key={item.id + "commentDisplay"} 
showMore={showMore} 
item={item} 
id={item.id} >

<BorderDiv/>


<TopBarWrapper>

<img src={item.author_avatar}/>

<h3 style={{alignSelf: "center", fontSize: ".6em", gridArea: "nick", marginRight: "8px"}}>                                   {item.author_nick}
</h3>

<span style={{alignSelf: "center", gridArea: "date", fontSize: ".6em", color: "gray"}}></span>


</TopBarWrapper>

<CommentBody style={{gridArea: "body", fontSize: "15px"}}>
{item.body} (...the ID for this comment => {item.id}, and its children id's => {getReplyArray(item.comments)})                                    </CommentBody>

<BottomBarWrapper>

<Reply onClick={() => handleReplyButton(item.id)}>reply</Reply>

<VoteUp>

<svg viewBox="0 0 22 20" xmlns="http://www.w3.org/2000/svg"><path key={item.id + "path1"} data-id={ item.id + "path1"} d="M10.74.04a2.013 2.013 0 00-1.58 1.88c-.11 2.795-.485 4.45-2.283 6.946a1.272 1.272 0 00-1.065-.58h-4.55C.573 8.287 0 8.84 0 9.507v8.773c0 .667.572 1.218 1.263 1.218h4.55c.435 0 .821-.22 1.049-.548.263.204.506.387.758.533.417.24.887.384 1.532.45 1.29.128 3.403.032 8.283.052a.53.53 0 00.317-.113c1.224-.667 4.255-5.775 4.248-10.534-.026-1.138-.542-1.78-1.532-1.78H13.96c.388-2.47.131-4.738-.735-6.208C12.76.555 12.078.111 11.403.018a2.035 2.035 0 00-.663.022m2.154 7.912c-.055.28.201.58.498.58h6.934c.356.035.67.091.67.913 0 1.047-.168 2.886-1.031 5.057-.865 2.172-2.155 4.531-2.603 4.455-1.215.08-7.014.109-8.108 0-.556-.056-.818-.135-1.113-.306-.266-.152-.59-.423-1.066-.791v-7.6c2.349-2.88 2.979-5.302 3.096-8.3.338-1.495 1.702-1.082 2.179-.13.697 2.402.879 4.442.544 6.122M1.263 9.262h4.55c.148 0 .251.1.251.244v8.773c0 .144-.103.243-.252.243h-4.55c-.148 0-.251-.099-.251-.243V9.506c0-.144.103-.244.252-.244"></path>

</svg>
<span></span>

</VoteUp>

<VoteDown>
<svg viewBox="0 0 22 20" xmlns="http://www.w3.org/2000/svg"><path key={item.id + "path2"} data-id={ item.id + "path2"} d="M11.26 19.96a2.013 2.013 0 001.58-1.881c.11-2.794.484-4.45 2.282-6.945.224.345.618.58 1.066.58h4.548c.692 0 1.264-.553 1.264-1.22V1.722c0-.668-.572-1.22-1.264-1.22h-4.548c-.436 0-.823.22-1.05.55a6.898 6.898 0 00-.759-.534c-.416-.24-.887-.384-1.531-.45C11.558-.06 9.445.037 4.564.017a.521.521 0 00-.316.114C3.023.796-.007 5.904 0 10.663c.025 1.138.541 1.78 1.532 1.78H8.04c-.39 2.47-.131 4.738.735 6.208.467.794 1.148 1.238 1.823 1.331a2.034 2.034 0 00.663-.022m-2.155-7.913c.056-.28-.202-.579-.497-.579H1.674c-.356-.035-.67-.091-.67-.913 0-1.047.166-2.886 1.031-5.057C2.9 3.326 4.19.967 4.638 1.044c1.214-.081 7.014-.109 8.108 0 .556.055.818.134 1.113.305.265.152.59.423 1.066.791v7.6c-2.349 2.88-2.979 5.302-3.096 8.3-.338 1.495-1.702 1.083-2.179.13-.697-2.402-.88-4.442-.545-6.123m11.631-1.309h-4.548c-.149 0-.252-.1-.252-.244V1.722c0-.144.103-.244.252-.244h4.548c.15 0 .253.1.253.244v8.772c0 .144-.103.244-.253.244"></path>                     </svg>                                

<span></span>
</VoteDown>


<span style={{cursor: "pointer", marginLeft: "10px", fontSize: "10px", lineHeight: "40px"}} 
onClick={() => handleShowMoreButton(item.comments)}> 

{item.comments === undefined || item.comments.length == 0 ? "" :                                                           hideCommentsOrShowComments(item.comments)} 

</span>

</BottomBarWrapper>



<FormWrapper rows={rows} commentid={item.id}>

<img src={item.author_avatar}></img>
<Form 
id={item.id.toString() + "form"} 
className="form-inline" 
onSubmit={handleSubmitClick} 
enctype="multipart/form-data" >


<div style={{width: "100%", height: "100%"}} className="field" >

<textarea 
style={{width: "100%"}}
onChange={handleChange} 
index={1}
placeholder={"...reply to " }
name="comment"
onKeyPress={e => {

if(e.key === 'Enter')
e.preventDefault()
}}

value={"enter a reply..."}/>
</div>

</Form>

<button 
form={item.id.toString() + "form"} 
style={{marginTop: "3px", gridArea: "main_comment_buttons"}} 
type="submit">

reply now
</button>

</FormWrapper>

{nestedComments}
</CommentDisplay>

)}

</>
)
}



return (


<div style={{margin: "0 auto 90px auto"}}>

<div style={{background: "#d3f7b9"}}>

<ul style={{padding: "18px", margin: "0px 15px 0px 15px", width: "80vw"}}>
<li> <h2>Animation using React-spring useTransition not working as expected. All the divs get animated instead of only the respective divs when the "show/hide comments" button or the "reply" buttons are clicked. </h2></li>

<ul style={{margin: "10px 30px"}}>

<li>Each top level comment is mapped into the Comment function (Line 715) </li><br/>

<li>The Comment function (Line 548) recursively loops thru each top level comment's nested replies, replies of replies, replies of replies of replies etc.... adds useTansition to each and renders them.  </li><br/>

<li> When the show/hide button is clicked, it changes the boolean state for all its children to true causing the children to collapse out of view. This is the part i want to animate. Same thing when the reply button is clicked, the reply form should be animated.</li><br/>


</ul>
</ul>


</div>

<div style={{position: "relative"}}>
{allComments.map( (c) => {
return (
<Comment 
key={c.id} 
item={c} 
rows={rows} 
showMore={showMore} 
handleShowMoreButton={handleShowMoreButton}
handleReplyButton={handleReplyButton}/>
)
})}
</div>    
</div>

)
}




class App extends React.Component {

render() {
return (


<CommentSection/>

);
}
}


const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

我最终使用了一组refs来动画回复表单和显示/隐藏按钮。正是我拥有的所有setStates导致了许多渲染,并没有让CSS转换动画发挥作用。

链接到工作解决方案

function CommentSection(props){

//all the comments from server, usually in useeffect hook but hardcoded here instead
const artDataComments = [
{
"id": 295,
"body": "This is a First level comment to the main Story blah blah...",
"created_at": "2021-07-16T17:17:10.410Z",
"updated_at": "2021-07-16T17:17:10.410Z",
"original_comment_author": null,
"parent_id": null,
"ancestry": null,
"date": "less than a minute",
"comment_number": 256,
"reply": false,
"user_id": 1,
"commentable_type": "Story",
"commentable_id": 1,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "Jimmy",
"comments": [
{
"id": 296,
"body": "this is the first reply to the main comment ",
"created_at": "2021-07-16T17:17:49.585Z",
"updated_at": "2021-07-16T17:17:49.585Z",
"original_comment_author": "undefined",
"parent_id": 295,
"ancestry": "295",
"date": "less than a minute",
"comment_number": 257,
"reply": true,
"user_id": 1,
"commentable_type": "Comment",
"commentable_id": 295,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "izzy",
"comments": [
{
"id": 298,
"body": "Reply to the reply (3rd level)",
"created_at": "2021-07-16T17:22:46.088Z",
"updated_at": "2021-07-16T17:22:46.088Z",
"original_comment_author": "undefined",
"parent_id": 296,
"ancestry": "295/296",
"date": "less than a minute",
"comment_number": 259,
"reply": true,
"user_id": 1,
"commentable_type": "Comment",
"commentable_id": 296,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "Noel",
"comments": [
{
"id": 299,
"body": "another reply to a reply (4th level) etc...",
"created_at": "2021-07-16T17:23:10.561Z",
"updated_at": "2021-07-16T17:23:10.561Z",
"original_comment_author": "undefined",
"parent_id": 298,
"ancestry": "295/296/298",
"date": "less than a minute",
"comment_number": 260,
"reply": true,
"user_id": 1,
"commentable_type": "Comment",
"commentable_id": 298,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "Mitch",
"comments": []
}
]
}
]
},
{
"id": 297,
"body": "this is a second reply to the main comment .... ",
"created_at": "2021-07-16T17:18:59.249Z",
"updated_at": "2021-07-16T17:18:59.249Z",
"original_comment_author": "undefined",
"parent_id": 295,
"ancestry": "295",
"date": "less than a minute",
"comment_number": 258,
"reply": true,
"user_id": 1,
"commentable_type": "Comment",
"commentable_id": 295,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "mike",
"comments": []
}
]
},
{
"id": 294,
"body": "This is another First Level comment to the main story ... ",
"created_at": "2021-07-16T17:16:19.314Z",
"updated_at": "2021-07-16T17:16:19.314Z",
"original_comment_author": null,
"parent_id": null,
"ancestry": null,
"date": "less than a minute",
"comment_number": 255,
"reply": false,
"user_id": 1,
"commentable_type": "Story",
"commentable_id": 1,
"edit_history": "",
"author_avatar": "undefined",
"author_nick": "Natalie",
"comments": []
}
]
;

const allShowMoreRefs = useRef([]);
allShowMoreRefs.current = []
const allReplyRefs = useRef([]);
allReplyRefs.current = []

const getReplyArray = (childrenCommentArray) => {

let tempArray = []

childrenCommentArray.map( (x, i) => {

x.id
tempArray.push(x.id + ", ")

})

return tempArray.length > 0 ? tempArray : "blank"
}


const handleReplyButton = (childrenCommentArray, e, itemID) => {

allReplyRefs.current.map ( (current, i) => {

if (itemID == current.id.substr(0, current.id.indexOf('-'))){
if (current.classList.contains("replyForm")){
current.classList.remove("replyForm")

}else{
current.classList.add("replyForm")

}
}

})

}

const handleShowMoreButton = (childrenCommentArray, e, itemID) => {

//set the label
if (e.target.innerText == "hide replies"){
e.target.innerText = "show replies"
}else{
e.target.innerText = "hide replies"
}

//get the ref(s) and change the css
childrenCommentArray.map(item => {
allShowMoreRefs.current.map ( (current, i) => {

if (item.id == current.id){
if (current.classList.contains("shrink")){
current.classList.remove("shrink")
}else{
current.classList.add("shrink")
}

}
})
})


}





//function called recursivley depended on how many nested comments get returned from server
const Comment = ({ item, userState, storyID, setArtDataComments, handleShowMoreButton, handleReplyButton}) => {

const addToShowMoreRefs = (el) => {

if (el && !allShowMoreRefs.current.includes(el)){

allShowMoreRefs.current.push(el)

}

}

const addToReplyRefs = (el) => {

//console.log("size b4 going in addToReplyeRefs is ", allReplyRefs.current.length )
console.log("in================= addTo_Reply_Refs")

if (el && !allReplyRefs.current.includes(el)){
//console.log("inside================= addToReplyeRefs")
//console.log(el)
allReplyRefs.current.push(el)
console.log("size after adding one is ", allReplyRefs.current.length )
}

}


const nestedComments = (item.comments || []).map(com => {


return (

<div key={item.id}>

<Comment style={{border: "2px solid blue"}} 
item={com} type="child" 
userState={userState} 
storyID={storyID} 
setArtDataComments={setArtDataComments} 
handleShowMoreButton={handleShowMoreButton} 
handleReplyButton={handleReplyButton} />

</div>
)
});



return (

<CommentDisplay 
ref={addToShowMoreRefs} 
className={"replies"} 
key={item.id + "commentDisplay"} 
item={item} id={item.id} >

<BorderDiv/>

<TopBarWrapper>

<img src="defaultAvatar"/>

<h3 style={{alignSelf: "center", fontSize: ".6em", gridArea: "nick", marginRight: "8px"}}>
{item.author_nick}
</h3>

<span style={{alignSelf: "center", gridArea: "date", fontSize: ".6em", color: "gray"}}></span>

</TopBarWrapper>

<CommentBody style={{gridArea: "body", fontSize: "15px"}}>
{item.body} this comment ID is {item.id} and its children array is {getReplyArray(item.comments)}
</CommentBody>


<BottomBarWrapper>

<Reply onClick={(e) => handleReplyButton(item.comments, e, item.id)}>reply</Reply>

<VoteUp onClick={(e)=>{handleVoteUp(e, item.id)}}>

<svg viewBox="0 0 22 20" xmlns="http://www.w3.org/2000/svg"><path key={item.id + "path1"} data-id={ item.id + "path1"} 
      d="M10.74.04a2.013 2.013 0 00-1.58 1.88c-.11 2.795-.485 4.45-2.283 
6.946a1.272 1.272 0 00-1.065-.58h-4.55C.573 8.287 0 8.84 0 9.507v8.773c0 .667.572 1.218 1.263 1.218h4.55c.435 0 .821-.22 1.049-.548.263.204.506.387.758.533.417.24.887.384 1.532.45 1.29.128 3.403.032 8.283.052a.53.53 0 00.317-.113c1.224-.667 4.255-5.775 4.248-10.534-.026-1.138-.542-1.78-1.532-1.78H13.96c.388-2.47.131-4.738-.735-6.208C12.76.555 12.078.111 11.403.018a2.035 2.035 0 00-.663.022m2.154 7.912c-.055.28.201.58.498.58h6.934c.356.035.67.091.67.913 0 1.047-.168 2.886-1.031 5.057-.865 2.172-2.155 4.531-2.603 4.455-1.215.08-7.014.109-8.108 0-.556-.056-.818-.135-1.113-.306-.266-.152-.59-.423-1.066-.791v-7.6c2.349-2.88 2.979-5.302 3.096-8.3.338-1.495 1.702-1.082 2.179-.13.697 2.402.879 4.442.544 6.122M1.263 9.262h4.55c.148 0 .251.1.251.244v8.773c0 .144-.103.243-.252.243h-4.55c-.148 0-.251-.099-.251-.243V9.506c0-.144.103-.244.252-.244"></path></svg>
<span commentid={item.id}>{item.total_upvotes}</span>

</VoteUp>

<VoteDown onClick={(e)=>{handleVoteDown(e, item.id)}}>

<svg viewBox="0 0 22 20" xmlns="http://www.w3.org/2000/svg"><path key={item.id + "path2"} data-id={ item.id + "path2"} d="M11.26 19.96a2.013 2.013 0 001.58-1.881c.11-2.794.484-4.45 2.282-6.945.224.345.618.58 1.066.58h4.548c.692 0 1.264-.553 1.264-1.22V1.722c0-.668-.572-1.22-1.264-1.22h-4.548c-.436 0-.823.22-1.05.55a6.898 6.898 0 00-.759-.534c-.416-.24-.887-.384-1.531-.45C11.558-.06 9.445.037 4.564.017a.521.521 0 00-.316.114C3.023.796-.007 5.904 0 10.663c.025 1.138.541 1.78 1.532 1.78H8.04c-.39 2.47-.131 4.738.735 6.208.467.794 1.148 1.238 1.823 1.331a2.034 2.034 0 00.663-.022m-2.155-7.913c.056-.28-.202-.579-.497-.579H1.674c-.356-.035-.67-.091-.67-.913 0-1.047.166-2.886 1.031-5.057C2.9 3.326 4.19.967 4.638 1.044c1.214-.081 7.014-.109 8.108 0 .556.055.818.134 1.113.305.265.152.59.423 1.066.791v7.6c-2.349 2.88-2.979 5.302-3.096 8.3-.338 1.495-1.702 1.083-2.179.13-.697-2.402-.88-4.442-.545-6.123m11.631-1.309h-4.548c-.149 0-.252-.1-.252-.244V1.722c0-.144.103-.244.252-.244h4.548c.15 0 .253.1.253.244v8.772c0 .144-.103.244-.253.244"></path></svg>
<span  commentid={item.id}>{item.total_downvotes}</span>

</VoteDown>

<span 
style={{cursor: "pointer", marginLeft: "10px", fontSize: "10px", lineHeight: "40px"}} 
onClick={(e) => handleShowMoreButton(item.comments, e, item.id)}> 

{item.comments === undefined || item.comments.length == 0 ? "" : "hide replies"}

</span>
</BottomBarWrapper>


<div 
id={item.id + "-replyform"} 
className={"replyFormHidden"} 
ref={props.addToReplyRefs} 
commentid={props.commentid}
ref={addToReplyRefs}
originalcommentAuthor={item.author_nick}
userState={userState}
storyID={storyID}
commentid={item.id}
setArtDataComments={setArtDataComments}
handleReplyButton={handleReplyButton}>

<img src="defaultManIcon"></img>
<Form 
id={item.id + "form"} 
className="form-inline" 
onSubmit="handleAdd" 
enctype="multipart/form-data" >

<div style={{width: "100%", height: "100%"}} className="field" >


<Textarea
type="textarea"
className="form-control"
index={1}
placeholder={"...reply to " + props.commentAuthor}
name="comment"
onKeyPress={e => {
if(e.key === 'Enter')
e.preventDefault()
}}/>

</div>
</Form>
<button 
form={item.id + "form"} 
style={{marginTop: "3px", gridArea: "main_comment_buttons"}} 
type="submit" >
reply now
</button>
</div>

{nestedComments}

</CommentDisplay>
)
}

return (

<Comments>

<div>
<div style={{position: "relative"}}>

{
artDataComments.map( (c, i) => {
return (
<div key={c.id}>

<Comment 
item={c} 
userState={props.userState} 
handleShowMoreButton={handleShowMoreButton} 
handleReplyButton={handleReplyButton} />
</div>

)
})
}

</div>

</div>
</Comments>

);
}