updateLastConsumedMessageIndex зависает, что не приводит к обновлению сообщений
Когда компонент установлен, канал либо берется из существующего, либо создается новый. Этот канал позже сохраняется в состоянии для постоянства в компоненте. При щелчке по компоненту все сообщения канала обновляются до потребляемых.
Код относится к столбцу "Сегодняшний канал сдвига". Код правой стороны отдельный.
Senario: когда я нажимаю User, вызывается onTaskSelect, который запускает весь пользовательский чат справа после установки всех потребляемых сообщений. здесь возникает проблема 1 и 2. Теперь я нажимаю другого пользователя и возвращаюсь к ранее выбранному пользователю, возникает проблема 3.
Проблемы:
1) Не обновляет использованные сообщения и всегда возвращает ноль.
2) Он перестает получать новые сообщения от прослушивателя .on, вызываемого в функции joinOrCreate.
3) при повторяющемся ответе на щелчок с ошибкой
SyncError: доступ запрещен для идентификации (статус: 403, код: 54007) в mapTransportError (http://localhost:3000/static/js/0.chunk.js:162153:12) в http://localhost:3000/static/js/0.chunk.js:162210:20
ПРИМЕЧАНИЕ. Каналы настраиваются один раз и никогда не уходят, если страница не обновляется.
ПРИМЕЧАНИЕ. Весь чат с правой стороны работает нормально и находится в отдельном модуле.
ПРИМЕЧАНИЕ. Клиент был инициализирован в начале приложения как контекст, который сохраняется в течение всего жизненного цикла приложения от открытия до закрытия.
const TaskCard = props => {
const [lastMessage, setLastMessage] = useState({})
const [open, setOpen] = useState(false)
const [unread, setUnread] = useState(0)
const [channel, setChannel] = useState({})
const joinOrCreate = useCallback(async() => {
try{
const fetchedChannel = await props.client.getChannelByUniqueName(props.task.id.toString())
let joined = fetchedChannel
if(fetchedChannel.state.status !== "joined") {
joined = await fetchedChannel.join()
}
console.log()
joined.getMessages()
.then(messages => {
if(messages.items.length > 0) {
if(joined.lastConsumedMessageIndex < messages.items.length - 1) {
setUnread(true)
}
const recent_message = messages.items[messages.items.length - 1]
const limit_message = recent_message.body.slice(0,14)
setLastMessage({
body: limit_message.length === 14? (limit_message + '...') : limit_message,
time: recent_message.timestamp,
index: recent_message.index,
})
}
})
joined.on('messageAdded', messageUpdated)
setChannel(joined)
}
catch(ch) {
console.log(ch)
try{
const newChannel = await props.client.createChannel({
uniqueName: props.task.id.toString(),
friendlyName: 'General Chat Channel'
})
let joined = newChannel
if(newChannel.state.status !== "joined") {
joined = await newChannel.join()
}
joined.getMessages()
.then(messages => {
if(messages.items.length > 0) {
const recent_message = messages.items[messages.items.length - 1]
setLastMessage({
body: recent_message.body,
time: recent_message.timestamp,
})
}
})
joined.on('messageAdded', messageUpdated)
setChannel(joined)
}
catch(e) {
console.log(e)
}
}
}, [props.client, props.task.id])
const messageUpdated = message => {
const limit_message = message.body.slice(0,14)
setLastMessage({
body: limit_message.length === 14? (limit_message + '...') : limit_message,
time: message.timestamp,
index: message.index
})
}
const onTaskSelect = () => {
// console.log(lastMessage.index)
console.log(channel.uniqueName)
if(lastMessage.body) {
channel.updateLastConsumedMessageIndex(+lastMessage.index)
.then(res => {
console.log(res)
})
.catch(e => {
// console.log(props.client)
// console.log(channel)
console.log(e)
})
}
props.onTaskClick(props.task.id.toString())
}
useEffect(() => {
if(props.channelId === props.task.id) {
setOpen(true)
setUnread(false)
}
else {
setOpen(false)
}
}, [props.channelId, props.task.id])
useEffect(() => {
joinOrCreate()
}, [joinOrCreate])
useEffect(() => {
if(channel.lastConsumedMessageIndex < lastMessage.index && !open) {
setUnread(true)
}
}, [channel.lastConsumedMessageIndex, lastMessage, open])
return (
<Row key={props.task.id} >
<Col className='justify-center'>
<Card className={'more-than-90 ' + (open? 'background-active' : null)}
onClick={e => onTaskSelect()}
>
<Row>
<Col md={2} style={{alignSelf: 'center', paddingLeft:'15px'}}>
{
props.task.worker.pic_url === "" || props.task.worker.pic_url === null ?
<div className="name-image">
{props.task.worker.first_name[0] + props.task.worker.last_name[0]}
</div>
:
<Image width={50} height={50} src={props.task.worker.pic_url} roundedCircle />
}
</Col>
<Col md={10}>
<Row>
<Col md={8}>
<p style={{fontSize:'.9rem'}}>{props.task.worker.name}</p>
</Col>
<Col>
<p style={{fontSize:'.7rem'}} className='left-align-text'>{lastMessage.time? moment(lastMessage.time).format('hh:mm A') : null}</p>
</Col>
</Row>
<Row>
<Col md={8}>
<p style={{fontSize:'.7rem'}}>{lastMessage.body? lastMessage.body : null}</p>
</Col>
<Col>
{
unread ?
<FontAwesomeIcon
icon={faEnvelopeOpenText}
size="lg"
color={"#0064bb"}
/>
:
null
}
</Col>
</Row>
</Col>
</Row>
</Card>
</Col>
</Row>
)
}
1 ответ
Проповедник разработчиков Twilio здесь.
Я думаю, что Уилл Сэмс в своем комментарии был прав. Вам действительно необходимо установить индекс непрочитанных сообщений, чтобы канал мог иметь действительный индекс непрочитанных сообщений. Из документов:
Примечание. Чат не устанавливает горизонт потребления автоматически. Если вы не зададите это явно в своем приложении, горизонт потребления не будет существовать для пользователя в канале. Без горизонта потребления горизонт потребления вашего пользователя (состояние чтения) не будет правильно синхронизироваться между клиентами. Если для пользователя не установлен горизонт потребления на канале, получение непогашенных сообщений всегда будет возвращать 0. Если член канала не имеет статуса потребления, его последний использованный индекс и отметка времени будут нулевыми или нулевыми в зависимости от платформы.
Итак, при создании канала я бы установил сообщения канала как неиспользованные, чтобы начать эту меру. Вы также можете использовать функциюsetAllMessagesConsumed
вместо того, чтобы читать индекс последнего сообщения.
Я также заметил, что когда вы устанавливаете последнее сообщение, вы пропускаете установку его индекса в одной точке:
const recent_message = messages.items[messages.items.length - 1]
setLastMessage({
body: recent_message.body,
time: recent_message.timestamp,
})
что могло вызвать проблемы.
Меня беспокоит способ настройки ваших обратных вызовов и эффектов. Когда вы запускаетеonTaskSelect
похоже, что вы отправляете идентификатор задачи обратно родителю.
props.onTaskClick(props.task.id.toString());
Предположительно это так, чтобы вы могли видеть все сообщения на главной панели.
Однако я также предполагаю, что это устанавливает задачу в родительском элементе, которая затем передается как props.tasks
этому ребенку. ВjoinOrCreate
обратный вызов настроен на обновление, когда props.task.id
обновляется и useEffect
основан на joinOrCreate
меняется. Я предполагаю, что всякий раз, когда вы переходите между задачами, вы запускаете очистку и повторную оценкуjoinOrCreate
. За исключением того, что здесь нет функции очистки, поэтому вы каждый раз перезагружаете канал для каждого из этих компонентов. Я предполагаю, что это как-то связано с нарушением событий и возможными ошибками, которые вы получаете при повторном нажатии.
Вместо этого я бы, вероятно, переделал это так, чтобы TaskCard
Компонент не контролирует жизненный цикл объекта канала. Я бы загрузил и присоединил к списку каналов, которые вы собираетесь отображать в родительском компоненте, а затем передал бы объект канала вTaskCard
. Это упростит компоненты, поскольку родитель будет иметь дело с данными, аTaskCard
мог справиться только с визуализацией. Это также будет означать, что при изменении статуса карты (с показа на не показ) вы только повторно визуализируете данные. Таким образом, вы также можете поделиться объектом канала междуTaskCard
и вид чата справа от скриншота (в противном случае я предполагаю, что вам придется загрузить его и в этот компонент, и это, вероятно, тоже не поможет).
Это всего лишь некоторые идеи, основанные на том, что я вижу в вашем приложении. Надеюсь, они помогут!