簡體   English   中英

updateLastConsumedMessageIndex 凍結導致消息中沒有更新

[英]updateLastConsumedMessageIndex freezes causing no update in messages

當組件被安裝時,通道要么從現有的抓取,要么創建一個新的。 此通道稍后會保存在 state 中,以便在組件中保持持久性。 單擊組件時,所有通道消息都會更新為已使用。

該代碼屬於“今日輪班頻道”欄目。 右側代碼是單獨的。

Senario:當我單擊一個用戶時 onTaskSelect 被調用,這會在設置所有消耗的消息后觸發右側的整個用戶聊天。 這里出現問題 1 和 2 現在我單擊另一個用戶並單擊返回到以前單擊的用戶問題 3 發生

問題:
1) 它不更新消費的消息並且總是返回零。
2) 它停止接收來自joinOrCreate function中調用的 .on 偵聽器的新消息。
3)關於錯誤的重復點擊響應
SyncError:在mapTransportError( http://localhost:3000/static/js/0.chunk.js:162153:12 )在http://localhost:localhost: 12處禁止訪問身份(狀態:403,代碼:54007) /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>
    )
}

在此處輸入圖像描述

Twilio 開發人員布道師在這里。

我認為 Will Sams 的評論很有道理。 您確實需要設置一個未讀索引以使通道開始,然后才能具有有效的未讀索引。 從文檔:

注意:聊天不會自動設置消費范圍 如果您未在應用程序中明確設置此選項,則通道內的用戶將不存在消費范圍。 如果沒有消耗范圍,您的用戶的消耗范圍(讀取狀態)將無法在客戶端之間正確同步。 如果用戶沒有在頻道上設置消費范圍,則獲取未消費的消息將始終返回 0 如果 Channel 的成員沒有消費狀態,則他們的最后消費索引和時間戳將為 null 或 0,具體取決於平台。

因此,在創建頻道時,我會將頻道的消息設置為未使用以啟動該措施。 您還可以使用 function setAllMessagesConsumed而不必讀取最后一條消息的索引。

我還注意到,當您設置最后一條消息時,您錯過了在某一點設置其索引:

                        const recent_message = messages.items[messages.items.length - 1]
                        setLastMessage({
                            body: recent_message.body,
                            time: recent_message.timestamp,
                        })

這可能會造成麻煩。

我擔心你的回調和效果的設置方式。 當您觸發onTaskSelect時,它看起來好像您將任務 ID 發送回父級。

props.onTaskClick(props.task.id.toString());

大概是這樣您就可以在主面板中看到所有消息。

但是,我還假設這會在父級中設置一個任務,然后將其作為props.tasks傳遞給該子級。 props.task.id更新並且useEffectjoinOrCreate更改為前提時, joinOrCreate回調設置為更新。 所以我的猜測是,每當您在任務之間進行更改時,都會觸發joinOrCreate的清理和重新評估。 除了沒有清理 function 之外,因此您最終每次都為這些組件中的每一個重新加載通道。 我猜想這與破壞事件以及再次單擊時出現的最終錯誤有關。

相反,我可能會重新設計它,以便TaskCard組件不控制通道 object 的生命周期。 我將加載並加入您打算在父組件中渲染的頻道列表,然后將頻道 object 傳遞給TaskCard 這將簡化組件,因為父級將處理數據,而TaskCard可以只處理渲染。 這也意味着當卡片的狀態發生變化(從顯示到不顯示)時,您只是重新渲染數據。 這樣,您還可以在任務卡和屏幕截圖右側的聊天視圖之間共享頻道TaskCard (否則我猜您也必須在該組件中加載它,這可能也無濟於事)。

這些只是基於我在您的應用程序中看到的一些想法。 我希望他們有所幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM