计算状态碰巧晚了
Calculating state happens to late
我想做一个简单的点赞按钮,它有合适的颜色,取决于它是否被点赞。我尝试使用 React.useEffect 提前计算(在 return 之前),但似乎是在之后计算的...我可以看到它,因为所有的心,没有颜色,但是当我进行软重载时,它们会变成正确的颜色...有人知道我在这里做错了什么吗?
const Hart = ({subject}) => {
const [liked, setLiked] = useState(false);
const [hasloaded,setHasloaded] = useState(false);
const [ownId, setOwnId] = useState('');
const [token, setToken] = useState('');
const [favourite, setFavourite] = useState([]);
const favouriteId = [];
React.useEffect(()=> {
const constructor = async () => {
await refreshToken();
//favourites contains all the favorite subjects
//This calculates the boolean to check if the subject is liked or not
//This array is calculated with axios, and is correct
for(let i = 0; i<favourite.length; i++) {
if(favourite[i].id === subject.id) setLiked(true)
}
setHasloaded(true);
console.log("done")
}
constructor();
},[])
if(!hasloaded) return null;
else{
return (
<Pressable style= {styleSubjectList.heartIcon} onPress={() => checkFavorite()}>
<MaterialCommunityIcons
name={liked ? "heart" : "heart-outline"}
size={20}
color={liked ? "red" : "white"}
/>
</Pressable>
);
}
};
export default Hart;
函数 constructor
是异步的,您正在设置两个状态,这两个状态也是异步函数。因此,最终触发 setLiked
的 for 循环不会在 sethasLoaded
设置为 true 之前完成。您需要同步这两个操作。
const constructor = async () => {
await refreshToken();
for(let i = 0; i<favourite.length; i++) {
if(favourite[i].id === subject.id) setLiked(true)
}
}
constructor().then(() => setHasloaded(true)).catch(e => console.log(e))
React.useEffect(()=> {
const constructor = async () => {
await refreshToken();
let token = await getAccessToken();
setToken(token);
let id = await getFromStore("ownId");
id = removeFirstAndLast(id)
setOwnId(id)
const axios = require('axios' );
const config = {
method: 'get',
url: backendURL + '/userManagement/users/' + id,
headers: {
'Authorization': 'Bearer ' + JSON.parse(token)
}
};
axios(config)
.then(function (response) {
setFavourite(response.data.favouriteSubjects)
// console.log(response.data.favouriteSubjects)
})
.catch(function (error) {
console.log(error);
});
for(let i = 0; i<favourite.length; i++) {
if(favourite[i].id === subject.id) setLiked(true)
}
}
constructor().then(() => {
setHasloaded(true);
console.log("done");
}).catch(e=>console.log(e));
},[])
我想做一个简单的点赞按钮,它有合适的颜色,取决于它是否被点赞。我尝试使用 React.useEffect 提前计算(在 return 之前),但似乎是在之后计算的...我可以看到它,因为所有的心,没有颜色,但是当我进行软重载时,它们会变成正确的颜色...有人知道我在这里做错了什么吗?
const Hart = ({subject}) => {
const [liked, setLiked] = useState(false);
const [hasloaded,setHasloaded] = useState(false);
const [ownId, setOwnId] = useState('');
const [token, setToken] = useState('');
const [favourite, setFavourite] = useState([]);
const favouriteId = [];
React.useEffect(()=> {
const constructor = async () => {
await refreshToken();
//favourites contains all the favorite subjects
//This calculates the boolean to check if the subject is liked or not
//This array is calculated with axios, and is correct
for(let i = 0; i<favourite.length; i++) {
if(favourite[i].id === subject.id) setLiked(true)
}
setHasloaded(true);
console.log("done")
}
constructor();
},[])
if(!hasloaded) return null;
else{
return (
<Pressable style= {styleSubjectList.heartIcon} onPress={() => checkFavorite()}>
<MaterialCommunityIcons
name={liked ? "heart" : "heart-outline"}
size={20}
color={liked ? "red" : "white"}
/>
</Pressable>
);
}
};
export default Hart;
函数 constructor
是异步的,您正在设置两个状态,这两个状态也是异步函数。因此,最终触发 setLiked
的 for 循环不会在 sethasLoaded
设置为 true 之前完成。您需要同步这两个操作。
const constructor = async () => {
await refreshToken();
for(let i = 0; i<favourite.length; i++) {
if(favourite[i].id === subject.id) setLiked(true)
}
}
constructor().then(() => setHasloaded(true)).catch(e => console.log(e))
React.useEffect(()=> {
const constructor = async () => {
await refreshToken();
let token = await getAccessToken();
setToken(token);
let id = await getFromStore("ownId");
id = removeFirstAndLast(id)
setOwnId(id)
const axios = require('axios' );
const config = {
method: 'get',
url: backendURL + '/userManagement/users/' + id,
headers: {
'Authorization': 'Bearer ' + JSON.parse(token)
}
};
axios(config)
.then(function (response) {
setFavourite(response.data.favouriteSubjects)
// console.log(response.data.favouriteSubjects)
})
.catch(function (error) {
console.log(error);
});
for(let i = 0; i<favourite.length; i++) {
if(favourite[i].id === subject.id) setLiked(true)
}
}
constructor().then(() => {
setHasloaded(true);
console.log("done");
}).catch(e=>console.log(e));
},[])