#javascript #reactjs
#javascript #reactjs
Вопрос:
Я пишу этот компонент react для рендеринга всех чатов пользователя в приложении для чата. Список диалогов извлекается из конечной точки REST и устанавливается как переменная состояния. Когда новое сообщение поступает через сокет, я пытаюсь вывести диалог в списке в начало и пометить его другим цветом.
Код для этого выглядит следующим образом:
const [conversationsList, setConversationsList] = useState([]);
//When a new message arrives,
const markNewConversation = (message) => {
console.log(conversationsList); //Empty array
let newConversationList = conversationsList.map((conversationElement) => {
if (conversationElement.thread_id === message.thread_id) {
conversationElement.date_created = message.date_created;
conversationElement.new_for.push(user._id);
}
return conversationElement;
});
console.log(newConversationList);
newConversationList = newConversationList.sortBy(function (o) {
return o.date_created;
});
console.log(newConversationList); //Empty as well.
setConversationsList(newConversationList); //Whole screen goes black on this.
};
useEffect(() => {
if (user._id === null) history.push("/");
connectSocket();
socket.on("_messageIn", markNewConversation);
getThreads().then((threads) => {
threads.forEach((thread, index) => {
let allParticipants = thread.thread_participants;
threads[index].other_user = allParticipants.find((participant) => {
return participant._id != user._id;
});
});
setConversationsList(threads);
setIsLoading(false);
});
// returned function will be called on component unmount
return () => {
socket.off("_messageIn", markNewConversation);
};
}, []);
return conversationsList.map((conversation) => {
return(//magically appears inside this div.)
})
Проблема в том, что когда приходит новое сообщение, функция получает пустой массив, и весь экран становится пустым. Я даже не устанавливаю для массива значение пустой в любом месте. Где я ошибаюсь?
Комментарии:
1. Что это
//magically appears inside this div.
? Как на самом деле выглядит этот возврат.2. @DamianM я отображаю имена всех людей в разговоре в виде списка внутри возврата карты. И имена фактически отображаются в пользовательском интерфейсе. Но точно такой же массив состояний пуст внутри функции.
Ответ №1:
В этой функции вы изменяете объекты, это может вызвать странные ошибки.
let newConversationList = conversationsList.map((conversationElement) => {
if (conversationElement.thread_id === message.thread_id) {
conversationElement.date_created = message.date_created;
conversationElement.new_for.push(user._id);
}
return conversationElement;
});
это должно выглядеть так:
let newConversationList = conversationsList.map((conversationElement) =>
(conversationElement.thread_id === message.thread_id) ? {
...conversationElement,
date_created: message.date_created,
new_for: [...conversationElement.new_for, user.id]
} : {
...conversationElement,
new_for: [...conversationElement.new_for]
}
Комментарии:
1. Массив, даже до ввода этой функции отображения, пуст. Как вы можете видеть в первой строке
markNewConversation
функции.
Ответ №2:
В javascript существует концепция изменения состояния, и мы никогда не должны изменять объекты напрямую. Здесь вы допускаете ошибку в том, что при поступлении нового сообщения он заменяет весь объект новым и как бы повторно инициализирует его. Поэтому распределите состояние с помощью оператора распространения перед добавлением нового сообщения. Сделайте так:
let newConversationList = conversationsList.map((conversationElement) =>
(conversationElement.thread_id === message.thread_id) ? {
...conversationElement, //spread/copy like this before mutating
date_created: message.date_created,
new_for: [...conversationElement.new_for, user.id]
} : {
...conversationElement, //spread/copy like this before mutating
new_for: [...conversationElement.new_for]
}
Комментарии:
1. Массив, даже до ввода этой функции отображения, пуст. Как вы можете видеть в первой строке
markNewConversation
функции.2. Да, он может быть пустым при запуске, но во время выполнения он добавляет и изменяет предыдущий, когда мы играем с приложением, поэтому избегайте их прямого изменения, не создавая его копию.
3. К сожалению, изменение таким образом также не сработало..