简体   繁体   English

React - 为什么我指定scrollTop并且元素没有得到这个?

[英]React - Why i assign scrollTop and the element don't get this?

I construct a chat. 我构建了一个聊天。 I want when the component load or I get new message I can to go bottom of the scroll. 我想当组件加载或我收到新消息时我可以去滚动的底部。 Without React, I tried and it's work. 没有React,我尝试了它的工作。 With React, i don't success. 有了React,我没有成功。

Thanks for help 感谢帮助

I already tried in JavaScript and it works, I have already tried in React with refs, like the code in JavaScript. 我已经尝试过使用JavaScript,但是我已经在React中尝试使用refs,就像JavaScript中的代码一样。

const contentMsgElement = document.querySelector("#contentMsg");
contentMsgElement.scrollTop = contentMsgElement.scrollHeight;
import React from 'react';
import ReactDOM from 'react-dom';
import MessageChat from './message/messageChat';
import moment from 'moment';
import MessageDateHeader from './message/messageDateHeader';

class BodyChat extends React.Component
{
    constructor(props)
    {
        super(props);
        this.state = {
            socket:null,
            allMessages:[],
            dateNow:""
        };

        this.messageList = React.createRef();
    }

    componentDidMount()
    {
        const {socket,user} = this.props;

        this.setState({
            socket:socket,
            user:user
        },this.getLast10Msg);

        this.setState({
            dateNow:moment.utc().local().format("DD/MM/YY")
        });

        this.getNewMsg(socket);
    }

    componentDidUpdate(prevProps,prevState)
    {
        const prevAll = prevState.allMessages;
        const all = this.state.allMessages

        if(prevAll.length !== all.length)
        {
            if(this.messageList.current)
            {   
                const messageList = this.messageList.current;
                ReactDOM.findDOMNode(messageList).scrollTop = messageList.scrollHeight;
                console.dir(ReactDOM.findDOMNode(messageList));
            }
        }
    }


    getLast10Msg = () =>
    {
        const {socket} = this.state;

        socket.on("respGet10Msg",data => 
        {
            this.setState({
                allMessages:data
            });
        });
    }

  getNewMsg = socket =>
    {
        socket.on("respMsg",data => 
        {
            const newMsg = {
                userName:data.userName,
                MESSAGE:data.message,
                CODE_UTILISATEUR:data.userId,
                TIME:data.time,
                ID:(data.idMessage) ? "msg_" + data.idMessage : "tpm_" + data.idTpm
            };

            this.setState({
                allMessages:this.state.allMessages.concat(newMsg)
            });

            this.scrollToBottom();
        });
    }

    scrollToBottom = () =>
    {
        const contentMsg = this.messageList;
        console.log(contentMsg);
        contentMsg.scrollTop = contentMsg.scrollHeight;
    }
    msgDate = (time,displayDate) =>
    {
        const {dateNow} = this.state;
        const date = moment.utc(time).local().format("DD/MM/YY");
        const yesterday = moment.utc().local().subtract(1, 'days').format("DD/MM/YY");
        const currentDate = displayDate.date;
        const respDate = {...displayDate};

        if(date !== currentDate)
        {
            if(dateNow === date)
            {
                respDate.date = "Aujourd'hui";
            }
            else if(yesterday === date)
            {
                respDate.date = "Hier";
            }
            else
            {
                respDate.date = date;
            }
            respDate.display = true;
        }        
        else
        {
            respDate.display = false;
        }

        return respDate;
    }

    render()
    {
        const {allMessages,user} = this.state;
        let displayDate = {date:"",display:false};
        if(allMessages.length > 0)
        {
            const messages = allMessages.map(msg =>
            {
                const msgChat = <MessageChat 
                idMessage={msg.ID}
                userName={msg.userName}
                message={msg.MESSAGE}
                userId={msg.CODE_UTILISATEUR}
                time={msg.TIME}
                currentUser={user.CODE_UTILISATEUR}
                key={msg.ID}
                />;

                displayDate = this.msgDate(msg.TIME,displayDate);
                const msgDate = (displayDate.display) ? <MessageDateHeader date={displayDate.date}/> : "";
                return <React.Fragment>
                    {msgDate}
                    {msgChat}
                </React.Fragment>;
            }
            );

            return <div className="contentMsg" ref={this.messageList}>
                    {messages}
                    {("Aujourd'hui" !== displayDate.date) ? <MessageDateHeader date="Aujourd'hui"/> : ""}
                </div>;
        }
        else
        {
            return <div className="contentMsg">
                </div>;
        }
    }
}

export default BodyChat;
.contentMsg
    {
        display: grid;
        grid-gap: 0.2rem;
        overflow-y: auto;
        overflow-x: hidden;
    }

I except scroll when chat mount or update at the bottom but nothing append! 我除了在聊天安装时滚动或在底部更新但没有任何附加!

@anik islam Shojib @anik islam Shojib

i try and don't work 我试着不工作

 componentDidUpdate(prevProps,prevState) { if(this.messageList) { console.log("here"); console.log(this.messageList.offsetTop); window.scrollTo({ top:this.messageList.offsetTop, behavior: "smooth" // Optional, adds animation }) console.log(this.messageList.scrollTop); } } 

Put an invisible div to the bottom of your chat screen. 将一个不可见的 div放在聊天屏幕的底部。 (Inside contentMsg .) (Inside contentMsg 。)

<div style={{display: none}} />

Then, Define a ref in your constructor: 然后,在构造函数中定义一个ref

this.myRef = React.createRef()

Attach this ref to your invisible div : 将此ref附加到您的隐形div

<div style={{display: none}} ref={el => this.myRef = el} />

Then whenever you want to scroll to bottom (eg componentDidUpdate ), call this function: 然后,只要您想要滚动到底部(例如componentDidUpdate ),请调用此函数:

this.myRef.scrollIntoView();

i found the solution. 我找到了解决方案。 I don't know why the render is not finish and call the function componentDidUpdate before. 我不知道为什么渲染没有完成并且之前调用了函数componentDidUpdate。 so the first time we say the render had update and it works. 所以我们第一次说渲染有更新,它的工作原理。

I think it's a trick but if someone know a better solution. 我认为这是一个技巧,但如果有人知道更好的解决方案。

 componentDidUpdate(prevProps,prevState) { if(this.state.allMessages.length > 0 && prevState.allMessages.length !== this.state.allMessages.length) { this.setState({ changeHeight: true }); } if(this.state.changeHeight && this.state.changeHeight !== prevState.changeHeight) { let height = ReactDOM.findDOMNode(this).scrollHeight; ReactDOM.findDOMNode(this).scrollTop = height; this.setState({ changeHeight: false }); } } 

here is scroll code for react. 这里是反应的滚动代码。 this code works for I think will for you too 这段代码适用于我认为也适合你

 componentDidUpdate(prevProps,prevState)
    {
        const prevAll = prevState.allMessages;
        const all = this.state.allMessages

        if(prevAll.length !== all.length)
        {
            if(this.messageList.current)
            {   
                window.scrollTo({
                    top:this.messageList.offsetTop,
                    behavior: "smooth"  // Optional, adds animation
                })
                console.dir(ReactDOM.findDOMNode(messageList));
            }
        }
    }

you can use ref as like 你可以像使用ref一样

 return <div className="contentMsg" ref={(e) => this.messageList= e} >
                    {messages}
                    {("Aujourd'hui" !== displayDate.date) ? <MessageDateHeader 
                    date="Aujourd'hui"/> : ""}
                </div>;

This is also supposed to work but didn't work for me either 这也应该有效但对我来说也不起作用

  ReactDOM.findDOMNode(messageList).scrollTop = messageList.scrollHeight;

can you try one thing only run following section in your componentDidUpdate 你能尝试一下只运行componentDidUpdate中的一节吗?

componentDidUpdate(prevProps,prevState)
    {


                window.scrollTo({
                    top:this.messageList.offsetTop,
                    behavior: "smooth"  // Optional, adds animation
                })

    } 

and see if it works, if it does then something wrong with your condition 并查看它是否有效,如果它确实你的病情有问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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