0

In my app I want to make my element always scrolled to bottom after getting new logs. For some reason my logsRef.current.scrollTop has value of zero all the time. My logs do show on screen and in console. I am not sure why is this not working, I've tried to use different approaches using useLyaoutEffect() but nothing made logsRef.current.scrollTop value change, it stayed zero all the time.

//my Logs.jsx component
import { useEffect, useRef } from "react";
import Container from "./UI/Container";
import styles from "./Logs.module.css";

const Logs = ({ logs }) => {
  const logsRef = useRef(null);

  useEffect(() => {
    logsRef.current.scrollTop = logsRef.current.scrollHeight;
    console.log(logs);
    console.log(logsRef.current.scrollTop);
  }, [logs]);

  return (
    <Container className={`${styles.logs} ${styles.container}`}>
      <div ref={logsRef}>
        {" "}
        {logs.map((log, index) => (
          <p key={index}>{log}</p>
        ))}
      </div>
    </Container>
  );
};
export default Logs;

Also, I do render my Logs.jsx in BattlePhase.jsx component where I do my attack logic on click and I save logs using useState() hook.

//parts where i do save my logs in BattlePhase.jsx

const [logs, setLogs] = useState([]);

const attackHandler = () => {
//logs where pokemon on left attacked pokemon on right
setLogs((prevLogs) => [
              ...prevLogs,
              `${pokemonDataOne.name} attacked ${
                pokemonDataTwo.name
              } for ${attack.toFixed(2)} dmg`,
              `${pokemonDataTwo.name} died`,
            ])
}
...
 <Attack className={isActiveArrow}>
          <Button onClick={attackHandler}>Attack!</Button>
        </Attack>

My logs on render and in console. enter image description here

4
  • Please provide a minimal reproducible example. There should be enough code to exactly reproduce the error when run. Commented Jan 16, 2023 at 16:05
  • Thank you for commenting @Unmitigated. This is minimal as it gets, you may copy hooks and <div> element that has map function which returns logs to make reproducible example (reprex). My compiler doesn't shows syntax error but it just doesn't work as it is supposed to. Commented Jan 16, 2023 at 16:16
  • It does not reproduce the issue as you do not show where you are changing the logs. Commented Jan 16, 2023 at 16:17
  • I hope I've provided parts where I do change the logs. @Unmitigated Commented Jan 16, 2023 at 16:26

1 Answer 1

1

Slight long shot but it's possible that the ref is attached to the wrong element. Are you sure the element with the CSS property that makes it scrollable (overflow) isn't on <Container>?

//my Logs.jsx component
import { useLayoutEffect, useRef } from "react";
import Container from "./UI/Container";
import styles from "./Logs.module.css";

const Logs = ({ logs }) => {
  const logsRef = useRef(null);

  useLayoutEffect(() => {
    logsRef.current.scrollTop = logsRef.current.scrollHeight;
    console.log(logs);
    console.log(logsRef.current.scrollTop);
  }, [logs]);

  return (
    <Container className={`${styles.logs} ${styles.container}`} ref={logsRef}>
      <div>
        {" "}
        {logs.map((log, index) => (
          <p key={index}>{log}</p>
        ))}
      </div>
    </Container>
  );
};
export default Logs;

Also to confirm, you do need useLayoutEffect here.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for pointing out. I was not aware I need to specify overflow-y: scroll; to element in order to manipulate scroll. I was thinking logsRef.current.scrollTop = logsRef.current.scrollHeight; will affect scrolling behaviour alone. It works now! Also it works fine without useLayoutEffect().
You might have bugs in future if you don't useLayoutEffect here. In fact I think you will have one now. When logs updates, and the page is long enough to cause the scroll to kick in, it will actually use the scrollHeight of the container before that new log was added. This would cause a small offset issue. Probably as well when the component mounts you'll have errors in console since with useEffect on first mount you'd be referencing a DOM element that does not exist.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.