简体   繁体   中英

JavaScript. React. Redux. Async. Loop does not complete before rendering of DOM

I'm working on a Messagelist component in which I am pulling message data from an external API. Every message contains a UserId in which I'll use to query my own API for more user information. I put the list of foundUsers in my redux store and have connected my component. Before rendering to the DOM, my objective is to loop through each individual message and replace the userid with the name of its corresponding user.

The problem I'm having is that the loop does not appear to finish before rendering the component, giving me some strange behavior.

初始渲染

Half a second later

后循环

Here is my code:

    render(){
    let users = this.props.chatkit.roomUsers
    let userIds = users.map((user) => {
        return user.id
    })
    let roomMessages = this.props.messages
    let messages = []
    for(var i = 0; i < roomMessages.length; i++){
        //create a new field to give each message a unique id
        roomMessages[i].unique = roomMessages[i].senderId
        //create a new field to give each message the avatar from that user
        let matchingUserIndex = userIds.indexOf(roomMessages[i].senderId)
        if(matchingUserIndex >= 0){
            roomMessages[i].avatar = users[matchingUserIndex].avatar
        }

        //review messages
        let previous = {}
        if(i > 0){
            previous = roomMessages[i - 1]
        }
        let currentMessage = roomMessages[i]
        //check if consecutive messages are made by the same user
        if(currentMessage.senderId === previous.senderId && currentMessage.unique === previous.unique){
            //display user name and avatar as an empty string
            messages.push({...currentMessage, unique: "", avatar: ""})
        } else{
            //display the user name
            messages.push({...currentMessage})
        }
    }
    //transform the unique field to contain the name of the user 
    let updatedMessages = []
    for(var j = 0; j < messages.length; j++){
        let matchingIdIndex = userIds.indexOf(messages[j].unique)
        if(matchingIdIndex >= 0 && messages[j].unique !== ""){
            messages[j].unique = users[matchingIdIndex].name
            updatedMessages.push(messages[j])
        } else {
            updatedMessages.push(messages[j])
        }
    }

    let currentChatkitUser = this.props.chatkit.chatUser.id

    return(
        <div>
            {this.props.room && (
                <div 
                    style={{overflow: "scroll", overflowX: "hidden", maxHeight: "70vh"}}
                    ref={this.messageList}
                >
                    <ul style={{listStyle: "none"}} className="p-4 mb-0">
                        {updatedMessages.map((message, index) => {
                            return (
                                <li 
                                    className="mb-1"
                                    key={index}>
                                    <div>
                                        {message.unique && (
                                            <span 
                                                className="d-block font-weight-bold mt-3"
                                                style={{color: "#000323"}}
                                            >
                                                <img 
                                                    src={message.avatar} 
                                                    style={{width: "2.5rem"}}
                                                    className="rounded-circle mr-2"
                                                />
                                                {message.unique}
                                            </span>
                                        )}
                                        <span 
                                            className={message.senderId === currentChatkitUser ? 
                                                "muted-blue text-light rounded d-inline-block ml-5" : "bg-secondary text-light rounded d-inline-block ml-5" 
                                            }
                                            style={{padding:".25rem .5rem"}}
                                        >
                                            {message.text}
                                        </span>
                                    </div>
                                </li>
                            )
                        })}
                    </ul>
                    <TypingIndicator usersWhoAreTyping={this.props.usersWhoAreTyping}/>
                    <div 
                        style={{float: "left", clear: "both"}}
                        ref={this.messagesEnd}>     
                    </div>
                </div>
            )}
        </div>
    )
}

use state property(eg loading = true) at initial which wil return the rendering some loading DOM. and define a function performing all the loop activity and execute it in componentwillmount and when you finish looping set loading property of state to false by which you can make your DOM to render your list of user in render method. ( not sure if componentwillmount is deprecated ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM