检查项目是否被用户“喜欢”

时间:2019-11-26 12:05:32

标签: javascript reactjs react-hooks

我有一个项目数组,我在渲染内循环,对于每个项目,我想使用检查此相关性的函数来检查当前用户是否喜欢它。该函数请求API检查Likes表是否返回true或false。

下面的代码将导致无限循环。有什么想法可以最好地解决这个问题吗?

function exampleComponent() {
    const [items, setItems] = useState([]);
    const [hasLike, setHasLike] = useState(null);
    const user = useContext(UserContext);

    useEffect(()=> {
        //I get and set the array of items here
    })


    function checkHasLike(itemId, userId) {
        axios.post('/api/check-like', {
            itemId: itemId,
            userId: userId
        }).then(response=> {
            setHasLike(response.data); //this should return true or false.
        }, ()=>{
            //handle rejection
        }).catch(()=>{
            //handle errors
        })
    }

    return(
        <>
            //Renders Page and all related stuff
            items.map(item => { //This is for displaying the item

                checkHasLike(item.id, user.id); //this will cause infinite loop...

                {hasLike? /*code for displaying already liked button*/ : /*active like button*/ }

            })
        </>
    )

}

3 个答案:

答案 0 :(得分:0)

请勿直接在<head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script> <script src="https://code.jquery.com/jquery-1.12.4.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> </head> <ul id='sortable'> <li class='ui-state-default row'> <div class='col-sm-1 col-xs-2' data-toggle='modal' data-target='#confirm-edit' onclick='modificaModale()'> <i class='fas fa-edit iconeScheda'></i> </div> <div class='col-sm-1 col-xs-2' data-toggle='modal' data-target='#confirm-elimina-esercizio' onclick='eliminaModale()'> <i class='fas fa-trash-alt iconeScheda'></i> </div> <div class='col-sm-10 col-xs-10'> <b>Name of exercise</b> </div> </li> </ul> <div class="modal fade" id="confirm-elimina-esercizio" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="background: none"> <div class="modal-dialog"> <div class="modal-content"> <form action="eliminaScheda.php" method="post"> <input type="text" name="id" id="idElimina" style="display:none" /> <div class="modal-header"> <h3>Elimina</h3> </div> <div class="modal-body"> Sei sicuro di voler eliminare <span id="esercizioModale"></span>? </div> <div class="modal-footer"> <input type="submit" value="Conferma" /> <input type="button" data-dismiss="modal" value="Annulla" /> </div> </form> </div> </div> </div>函数中调用状态更新,因为render函数将调用重新渲染并再次调用render函数

使用render进行API请求,如下所示:

useEffect

答案 1 :(得分:0)

解决方案:

const LIKE_STATUS={
NOT_DEFINED:0,
PROCESSING:1,
LIKED:2,
NOT_LIKED:3
}
function exampleComponent() {
    const [items, setItems] = useState([]);
    const [hasLike, setHasLike] = useState(null);
    const user = useContext(UserContext);

    useEffect(()=> {
       const processingItemIds=[]
       items.forEach(item=>{
          if(!item.hasLike || item.hasLike===LIKE_STATUS.NOT_DEFINED){
              checkHasLike(item.id,userId);
              processingItemIds.push(item.id)
          }
       })
       setItems(items.map(item => 
           processingItemIds.includes(item.id)
               ? 
               ({...item,hasLike:LIKE_STATUS.PROCESSING})
               :
               item
              ))
    })


    function checkHasLike(itemId, userId) {
        axios.post('/api/check-like', {
            itemId: itemId,
            userId: userId
        }).then(response=> {
            setItems(items.map(item=>
                 item._id===itemId
                 ?
                 ({
                     ...item,
                     hasLike:response.data? 
                     LIKE_STATUS.LIKED:LIKE_STATUS.NOT_LIKED
                  })
                  :
                  item
             ); 
        }, ()=>{
            //handle rejection
        }).catch(()=>{
            //handle errors
        })
    }

    return(
        <>
            //Renders Page and all related stuff
            items.map(item => { //This is for displaying the item
                {hasLike? /*code for displaying already liked button*/ : /*active like button*/ }

            })
        </>
    )

}

答案 2 :(得分:0)

基于给出的帖子,这是我最后的工作实施。

function exampleComponent() {
const [items, setItems] = useState([]);
const user = useContext(UserContext);

/*Where I get the items I check if the item has a like and insert
'hasLike' property with the(true/false) value to the item in to the final array.*/
useEffect(()=> {
    setItems(await Promise.all(response.data.map(async item => {
        await checkHasLike(item, user.id);
        return item;
    })));
})

//checking if the item has a like and inserting the true/false value to the item.
async function checkHasLike(item, userId) {
    await axios.post('/api/check-like', {
        itemId: item.id,
        userId: userId
    }).then(response=>
        item['hasLike'] = response.data;
    }, ()=>{
        //handle rejection
    }).catch(()=>{
        //handle errors
    })
}

return(
    <>
        //Renders Page and all related stuff
        items.map(item => { //This is for displaying the item

            {item.hasLike? /*code for displaying already liked button*/ : /*active 
             like button*/ }

        })
    </>
)

}