Реагировать прокрутки страницы сверху после рендера с помощью useEffect - PullRequest
1 голос
/ 12 октября 2019

Моя проблема - всякий раз, когда я использую <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 голос
/ 12 октября 2019

Я продолжил поиск проблемы и нашел следующие решения

Keep scroll-y после повторного отображения

Но проблема в getSnapshotBeforeUpdate недоступнав хуках, как можно увидеть здесь

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>
    );
  }
}
0 голосов
/ 12 октября 2019

Если я правильно понял, вы хотите, чтобы ваш useEffect код запускался только один раз после VarianceGraph рендеринга.

Попробуйте добавить второй аргумент [] к вашему useEffect, иначе код вuseEffect будет работать после любого изменения состояния.

...