#react-native
#react-native
Вопрос:
итак, в настоящее время у меня открыто 2 симулятора. Каждый симулятор регистрируется как другой пользователь. Когда я вхожу в чат между этими 2 пользователями, сообщения отправляются в прямом эфире в сокете, что идеально.
Моя проблема:
Пример: если пользователь 1 находится на экране «Все сообщения», а пользователь 2 находится в чате. И пользователь 2 отправляет пользователю 1 сообщение, экран пользователя 1 автоматически не обновляется новым сообщением, мне нужно либо прокрутить, чтобы обновить, либо перейти с одной страницы на другую.
Как я должен реализовать, когда отправляется новое сообщение, оно отображается пользователю 1?
Вот мой код:
AllMessagesScreen.js
const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const[page,setPage]=useState(0);
const [refreshing, setRefreshing] = useState(false);
const loadPosts = async () => {
setLoading(true);
const response = await messagesApi.getMessages();
setLoading(false);
if(refreshing) setRefreshing(false);
if (!response.ok) return setError(true);
setError(false);
setPosts(response.data)
};
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
loadPosts();
});
return unsubscribe;
}, [navigation]);
return(
<FlatList
data={posts}
keyExtractor={(listing) => listing.id.toString()}
renderItem={({ item,index }) => (
<MessagesList
title={item.Post.title}
subTitle={item.Messages[0].message}
onPress={() => navigation.navigate(routes.CHAT,{message:item,index})}
/>
)}
ItemSeparatorComponent={
ListItemSeparator
}
refreshing={refreshing}
onRefresh={() => {
loadPosts()
}}
/>
Другими словами, когда сообщение отправляется на экране чата, я хочу, чтобы мой экран allmessages отображался повторно, в настоящее время он отображается только при прокрутке для обновления или перехода к экрану allmessages.
Если вам потребуется какая-либо дополнительная информация, пожалуйста, сообщите мне, я немедленно ее предоставлю. Спасибо
чат screen.js
function ChatScreen({route,navigation}) {
const message = route.params.message;
const [messages, setMessages] = useState([]);
const [refreshing, setRefreshing] = useState(false);
const [text, setText] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const [socket, setSocket] = useState(null);
const { user } = useAuth();
const index = route.params.index;
const updateView = route.params.updateView;
useEffect(() => {
const newsocket =io.connect("IPADDRESS")
setMessages(message.Messages)
newsocket.on('connect', msg => {
console.log(`user: ${user.id} has joined conversation ${message.id}`)
setSocket(newsocket)
newsocket.emit('subscribe', message.id);
});
newsocket.on("send_message", (msg) => {
console.log("this is the chat messages:", msg);
setMessages(messages => [msg, ...messages]);
});
return(()=>newsocket.close());
}, []);
Комментарии:
1. вам нужно постоянно открытое соединение с веб-сокетом (или что-то подобное), чтобы следить за новыми сообщениями. Прямо сейчас похоже, что вы выполняете вызов API только для фокусировки экрана и обновления плоского списка. Если ваш серверный сервер не может использовать веб-сокеты, вам нужно продолжать использовать api получения сообщений с интервалами, например, каждые 10 секунд или около того
2. @VaibhavVishal привет, у меня есть сокет, реализованный на самом экране чата, но не на экране allmessages, я должен создать другое соединение только для получения самого последнего сообщения, отправленного в чате, и добавить его на экран allmessages? Я также обновил свой код с помощью кода экрана чата.
3. в нашем случае у нас есть соединение, которое всегда просматривает список группы. И еще один просмотр сообщений группы, который открывается / закрывается, когда вы входите / выходите из группы, чтобы просмотреть все сообщения. Чтобы получить последние сообщения группы, у нас есть поле с именем lastMessage в каждой группе, поэтому, даже когда мы находимся в списке групп, соединение с сокетами обнаруживает изменения в группе и вас и показывает последнее сообщение. У нас также есть такие поля, как lastUpdated в схеме группы, чтобы помочь с подобными вещами
Ответ №1:
Допустим, у вас есть схема групп, подобная этой:
{
id: string;
name: string;
}
и схема сообщений, подобная этой:
{
id: string;
groupId: string;
text: string;
}
Теперь, чтобы распознать, что новое сообщение было отправлено в группе, вы можете добавить lastMessage
в схему группы, например:
{
id: string;
name: string;
lastMessage: Message;
}
Таким образом, при отправке нового сообщения соответствующая группа будет меняться, что приведет к тому, что веб-сокет выдаст событие, и вы получите обновленные данные.
В вашей базе данных в lastMessage
поле у вас может быть внешний ключ для сбора сообщений, но при отправке json во внешний интерфейс отправляется весь объект message. Также вам нужно будет обновить свою функцию для создания сообщений, чтобы обновить и группу lastMessage
.
Если у вас есть время создания в схеме сообщений, наличие lastMessage в группе также поможет с их сортировкой, например, отображение группы с последним сообщением сверху.
Комментарии:
1. В настоящее время у меня есть таблица разговоров и таблица сообщений. когда я отправляю сообщение пользователю, между двумя пользователями создается беседа, которая сохраняется в моей истории разговоров, в то же время отправленное сообщение также сохраняется в моей таблице сообщений. в моей таблице разговоров я должен добавить поле lastmessage, которое обновляется идентификатором сообщения последнего отправленного сообщения?
2. Да, это верно. И добавьте веб-сокет в список разговоров, точно так же, как вы сделали в списке сообщений. Но в сообщении создаются только новые сообщения, в диалоге существующий объект также может обновляться, поэтому вам придется тщательно объединять и избегать дубликатов
3. Я очень смущен тем, как это сделать на данный момент, альтернативой этому является повторный рендеринг экрана allmessages каждые 10 секунд?
4. Да, вызов
loadPosts
внутри setinterval. Что-то вроде этого:setInterval(loadPosts, 10000)
нужно зайти внутрь useEffect5. но, очевидно, вы рекомендуете правильный сокет?