#javascript #reactjs
#javascript #reactjs
Вопрос:
В строке setVotedPosts([…previousVotedPosts, postID]);
Я пытаюсь получить предыдущее значение votedPosts , но возвращаю самое новое значение.
полный код: https://github.com/silvertechguy/reddit-clone/blob/main/src/components/vote-buttons.js
Приложение в реальном времени: https://reddit-clone-official.vercel.app /
const VoteButtons = ({ post }) => {
const [isVoting, setVoting] = useState(false);
const [votedPosts, setVotedPosts] = useState([]);
useEffect(() => {
const votesFromLocalStorage =
JSON.parse(localStorage.getItem("votes")) || [];
setVotedPosts(votesFromLocalStorage);
}, []);
const handleDisablingOfVoting = (postId) => {
const previousVotedPosts = votedPosts;
setVotedPosts([...previousVotedPosts, postId]);
localStorage.setItem(
"votes",
JSON.stringify([...previousVotedPosts, postId])
);
};
const handleClick = async (type) => {
setVoting(true);
// Do calculation to save the vote.
let upVotesCount = post.upVotesCount;
let downVotesCount = post.downVotesCount;
const date = new Date();
if (type === "upvote") {
upVotesCount = upVotesCount 1;
} else {
downVotesCount = downVotesCount 1;
}
await db.collection("posts").doc(post.id).set({
title: post.title,
upVotesCount,
downVotesCount,
createdAt: post.createdAt,
updatedAt: date.toUTCString(),
});
// Disable the voting button once the voting is successful.
handleDisablingOfVoting(post.id);
setVoting(false);
};
const checkIfPostIsAlreadyVoted = () => votedPosts.includes(post.id);
Комментарии:
1.
previousVotedPosts
— это будет ссылаться на значение состояния перед вызовомsetVotedPosts
функции для обновления состояния. К какому предыдущему значениюvotedPosts
вы пытаетесь получить доступ?2. После обновления состояния (setVotedPosts ) и попытки получить обновленное состояние я всегда получаю обратно пустой массив.
3. Состояние обновляется асинхронно, компонент будет видеть обновленное состояние только после повторного рендеринга. Используйте
useEffect
hook, если вы хотите зарегистрировать обновленное состояние.4. Есть ли способ предотвратить запуск перехвата useEffect в первый раз?
5. Я хочу запускать useEffect каждый раз, когда votedPosts изменяется, добавляя его в массив зависимостей useEffect . Но я не хочу запускать его в первый раз.
Ответ №1:
Проблема
const previousVotedPosts = votedPosts;
В JavaScript массивы являются ссылочными типами, поэтому вы не можете просто создать новую копию массива, используя =
.
Попробуйте это решение
Клонируйте массив, используя синтаксис распространения ( ...
).
const handleDisablingOfVoting = (postId) => {
const previousVotedPosts = [...votedPosts];
setVotedPosts([...previousVotedPosts, postId]);
localStorage.setItem(
"votes",
JSON.stringify([...previousVotedPosts, postId])
);
};
Комментарии:
1. Спасибо за ваш ответ. Каждый раз, когда я пытаюсь добавить что-то в localStorage, новое значение перезаписывает существующее в localStorage. Это главная проблема для меня, и что заставило меня здесь задать главный вопрос.