【问题标题】:How save scroll position and add to state in React.js?如何在 React.js 中保存滚动位置并添加到状态?
【发布时间】:2020-04-11 23:03:10
【问题描述】:

我有 MainWrapper,其中 api 请求返回带有项目(20 个)的对象。数据 api 响应我传输到组件(路由中的主页)。在 MainWrapper 中有两个路由:主页面和详细页面。

<Switch>
  <Route
    exact
    path="/"
    render={(props) => (
      <PokemonCardContainer
        pokemons={pokemons}
        search={search}
        loading={loading}
        error={error}
        lastPokemonElementRef={lastPokemonElementRef}
        handleSearch={handleSearch}
      />
    )}
  />
  <Route exact path="/pokemon/:pokemonName" component={Pokemon} />
</Switch>

在主页中,我用项目构建列表。当我到达列表末尾时,更新 api 请求并在列表等中添加新的 20psc 项目。此外,每个项目旁边还有一个按钮,指向该项目的详细信息页面。 我想在转到详细信息页面时保存滚动位置,当我回来时,位置在我单击的元素上。 在作为主页的组件中,我创建了新状态:

const [scrollPosition, setScrollPosition] = useState([0, 0]);

接下来我做了一个点击处理程序,我可以在其中找到滚动的坐标:

const getCurrentScrollPosition = (e) => {
    e.preventDefault();
    let cordsAfterClick = [];
    let cords = ["scrollX", "scrollY"];
    cords.forEach((cord) => {
      cordsAfterClick.push(window[cord]);
    });
    console.log("Array with cords: ", cordsAfterClick);
    setScrollPosition(cordsAfterClick);
    console.log("State scrollPosition after update state: ", scrollPosition);
  };

ps:我看到setScrollPosition 没有更新状态... e.preventDefault() - 仅用于测试。 我使用:

useEffect(() => {
    window.scrollTo(scrollPosition[0], scrollPosition[1]);
  }, [scrollPosition]);

UPD:代码已更新。下面的 cmets 有助于理解这个问题。 状态:

const [scrollPosition, setScrollPosition] = useState({
    scrollX: 0,
    scrollY: 0,
  });

点击处理程序:

const getCurrentScrollPosition = (e) => {
    let cordsAfterClick = {};
    let cords = ["scrollX", "scrollY"];
    cords.forEach((cord) => {
      cordsAfterClick[cord] = window[cord];
    });
    localStorage.setItem("scrollCord", JSON.stringify(cordsAfterClick));
  };

使用效果:

useEffect(() => {
    setScrollPosition((prevScrollCord) => {
      return {
        ...prevScrollCord,
        ...JSON.parse(window.localStorage.getItem("scrollCord")),
      };
    });
    window.scrollTo(scrollPosition.scrollX, scrollPosition.scrollY);
  }, [scrollPosition.scrollX, scrollPosition.scrollY]);

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    你必须像这样在 useEffect 中监听滚动事件:

    useEffetch(() => {
      const handleScroll = e => {
       // set scroll values in state
      }
    
      window.addEventListener('scroll', handleScroll);
    
      // Remove listener when component unmounts
      window.removeEventListener('scroll', handleScroll);
    }, [])
    

    【讨论】:

    • 感谢您的评论!所以我想知道点击时的位置。如何将handleScroll传递给onClick中的组件?
    • 你不需要这样做,滚动位置已经存储在点击之前的状态,因为用户已经滚动到该项目。不用担心点击,滚动位置会一直处于状态。
    • 哦,我认为您还需要将滚动位置存储在 localStorage 中,因为当您更改路由时,组件被卸载并且状态消失了。所以你需要将它存储到localStorage,然后从那里访问它。
    • 是的,你是对的。组件已卸载。我不得不使用本地存储。但请注意,如果我不使用 settimeout,则组件没有时间渲染,并且滚动的位置错误。 codesandbox.io/s/pokemons-sxbld我的代码
    • 你是对的!谢谢你的解释 !!如果我设置一个固定的 PokemonCard 高度,一切正常!我将编辑我的问题,用您的解决方案对其进行补充,并注意您的回答对我有帮助! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    相关资源
    最近更新 更多