Приветствую.
Есть проблема, не могу найти решения. Буду очень признателен за "наводку" или решение.
Итак, есть компонент содержащий коллекцию эл-тов (ul). Объекты для коллекции (li) хранятся в стейте dialogs.
В useEffect
1) вызывается loadRows(), который загрузит первые 50 объектов и
2)подписка на SSE, который нужен для получения новых объектов dialog c api.
Остальные объекты могут подгружатся на скроле в loadRows(), когда срабатывает событие при достижении границы прокрутки (infinity scroll). Реализацию loadRows() не привожу за ненадобностью.
Суть проблемы:
Допустим сначала загрузился компонент списка - в dialogs 50 эл-тов, затем мы подвигали скроллом - стейт dialogs стал содержать 300 эл-тов.
Теперь срабатывает events.onmessage (прилетел dialog с апи) и в функции которая обрабатывает событие (onmessage), мы обращаемся к стейту dialogs - в нем окажется не 300, а 50 эл-тов. Т.е. в стейте будут сообщения полученные только при инициализации. Пытался использовать редакс, та же фигня (или 0 или 50) . Я думаю, что при вызове createEvents() в useEffect events.onmessage замыкает текущий контекст. Вопрос как можно выйти из такого положение. Есть ли какое-то решение?
Собственно вопрос: Как получить актуальные данные в state при использовании server side event в момент срабатывания события?
Пример кода
export default function ConversationList() {
let [dialogs, setDialogs] = useState([]);
let [events, setEvents] = useState(null);
useEffect( () => async() => {
await loadRows();
await createEvents();
}, []);
async function createEvents() {
if (events) events.close();
setEvents(events = new EventSource(apiHost + urlPaths.eventRegistration));
events.onmessage = (ev) => {
const parsedData = JSON.parse(ev.data);
const id = parsedData?.dialog?._id.toString();
setDialogs([parsedData?.dialog, ...dialogs?.filter((dialog) => dialog?._id.toString() !== id)]);
}
}
}