React useEffect重新渲染后页面滚动到顶部。

3

我的问题是 - 每当我使用<Tabs>组件时,onChange方法会调用handleTabChange函数。该组件再次被调用并重新渲染后,useEffect也会被调用。这导致我的页面向上滚动。

如何确保handleChange和useEffect不会导致页面向上滚动?

export function VarianceGraph({ variancesGraphData }) {
  if (variancesGraphData === undefined) {
    return null;
  }
  const [currentProject, setCurrentProject] = useState('All');
  const [currentTab, setCurrentTab] = useState('ABCD');
  const projectCodes = prepareProjectCodesForConsumption(variancesGraphData);
  let data = {};

  function handleProjectChange(event) {
    const { value } = event.target;
    setCurrentProject(value);
  }

  function handleTabChange(event, tabValue) {
    setCurrentTab(tabValue);
  }

  data = prepareProjectDataForRechartsConsumption(currentProject, variancesGraphData);
  const hideABCD = data.ABCD.length < 1;
  const hideBCDF = data['BCDF'].length < 1;

  useEffect(() => {
    if (hideABCD && hideBCDF) {
      setCurrentTab('None');
    } else if (hideABCD) {
      setCurrentTab('BCDF');
    } else if (hideBCDF) {
      setCurrentTab('ABCD');
    }
  });

  return (
    <Grid container direction="row" justify="flex-start" alignItems="flex-start">
      <Grid item xs={12}>

我尝试过 -

我需要在某些函数中使用setCurrentTab,以免无限渲染。

我尝试使用useLayoutEffect,但行为相同。

如果需要,我可以进一步编写组件代码。请帮忙。谢谢。

2个回答

1
如果我理解正确,您只希望在VarianceGraph渲染后运行一次useEffect代码。
尝试向useEffect添加第二个参数[],否则useEffect中的代码将在任何状态更改后运行。

0

我已经搜索了这个问题,并找到了以下解决方案:

重新渲染后保持滚动条位置不变

但问题是,在钩子中没有getSnapshotBeforeUpdate,可以在此处看到:

使用React Hooks获取getSnapshotBeforeUpdate

因此,最好的选择是将组件转换为类组件,并按照此处的示例进行操作:https://reactjs.org/docs/react-component.html#getsnapshotbeforeupdate

示例代码,在您的情况下,您可能需要绑定document.body.scrollHeight

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Are we adding new items to the list?
    // Capture the scroll position so we can adjust scroll later.
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // If we have a snapshot value, we've just added new items.
    // Adjust scroll so these new items don't push the old ones out of view.
    // (snapshot here is the value returned from getSnapshotBeforeUpdate)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}

我以前做过这个,但仍然有一些问题。我现在想不起来了。让我回家查一下。 - technazi
两种方法都显示相同的行为。由于数据用于返回组件,因此它会提供空数据。 - technazi
老实说,我得编辑一下我的问题,这甚至不是因为 useEffect。我已经移除了 useEffect,但它仍然会滚动回顶部。 - technazi
可能是您使用的网格布局存在问题,或者在渲染之间组件为空时,浏览器会丢失滚动位置。 - Dhananjai Pai
在 useEffect 函数中,有没有一个简单的解决方法可以滚动到底部?这将暂时解决我的问题。 - technazi
很奇怪,如果Chrome开发者工具(检查元素)打开,页面就无法滚动到顶部。 - technazi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接