我有一个项目数组,我在渲染内循环,对于每个项目,我想使用检查此相关性的函数来检查当前用户是否喜欢它。该函数请求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*/ }
})
</>
)
}
答案 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*/ }
})
</>
)
}