reactjs - 如何在加载 React 页面时滚动它?

标签 reactjs react-select

我想传递一个值作为 URL 中的哈希值 (myapp.com#somevalue),并在页面加载时让页面滚动到该项目 - 这正是自互联网诞生以来使用哈希片段的行为。我尝试使用scrollIntoView,但在iOS 上失败了。然后我尝试取消设置/设置 window.location.hash 但似乎存在竞争条件。仅当延迟大于 600ms 时才有效。

我想要一个更可靠的解决方案,并且不想引入不必要的延迟。当延迟太短时,它似乎滚动到所需的项目,但随后又滚动到页面顶部。您不会在这个演示中看到效果,但它发生在我的实际应用程序中 https://codesandbox.io/s/pjok544nrx第75行

  componentDidMount() {
    let self = this;

    let updateSearchControl = hash => {
      let selectedOption = self.state.searchOptions.filter(
        option => option.value === hash
      )[0];
      if (selectedOption) {
        // this doesn't work with Safari on iOS
        // document.getElementById(hash).scrollIntoView(true);

        // this works if delay is 900 but not 500 ms
        setTimeout(() => {
          // unset and set the hash to trigger scrolling to target
          window.location.hash = null;
          window.location.hash = hash;
          // scroll back by the height of the Search box
          window.scrollBy(
            0,
            -document.getElementsByClassName("heading")[0].clientHeight
          );
        }, 900);
      } else if (hash) {
        this.searchRef.current.select.focus();
      }
    };

    // Get the hash
    // I want this to work as a Google Apps Script too which runs in
    // an iframe and has a special way to get the hash
    if (!!window["google"]) {
      let updateHash = location => {
        updateSearchControl(location.hash);
      };
      eval("google.script.url.getLocation(updateHash)");
    } else {
      let hash = window.location.hash.slice(1);
      updateSearchControl(hash);
    }
  }

编辑:我跟踪了React的行,该行重新渲染页面,并因此在滚动位置已经滚动到我告诉它进入componentDidMount()的位置后重置滚动位置。这是this onestyle[styleName] = styleValue; 重新渲染页面时,它正在设置 react 选择框组件的输入框组件的宽度样式属性。执行此操作之前的堆栈跟踪看起来像

(anonymous) @   VM38319:1
setValueForStyles   @   react-dom.development.js:6426
updateDOMProperties @   react-dom.development.js:7587
updateProperties    @   react-dom.development.js:7953
commitUpdate    @   react-dom.development.js:8797
commitWork  @   react-dom.development.js:17915
commitAllHostEffects    @   react-dom.development.js:18634
callCallback    @   react-dom.development.js:149
invokeGuardedCallbackDev    @   react-dom.development.js:199
invokeGuardedCallback   @   react-dom.development.js:256
commitRoot  @   react-dom.development.js:18867
(anonymous) @   react-dom.development.js:20372
unstable_runWithPriority    @   scheduler.development.js:255
completeRoot    @   react-dom.development.js:20371
performWorkOnRoot   @   react-dom.development.js:20300
performWork @   react-dom.development.js:20208
performSyncWork @   react-dom.development.js:20182
requestWork @   react-dom.development.js:20051
scheduleWork    @   react-dom.development.js:19865
scheduleRootUpdate  @   react-dom.development.js:20526
updateContainerAtExpirationTime @   react-dom.development.js:20554
updateContainer @   react-dom.development.js:20611
ReactRoot.render    @   react-dom.development.js:20907
(anonymous) @   react-dom.development.js:21044
unbatchedUpdates    @   react-dom.development.js:20413
legacyRenderSubtreeIntoContainer    @   react-dom.development.js:21040
render  @   react-dom.development.js:21109
(anonymous) @   questionsPageIndex.jsx:10
./src/client/questionsPageIndex.jsx @   index.html:673
__webpack_require__ @   index.html:32
(anonymous) @   index.html:96
(anonymous) @   index.html:99

我不知道将滚动页面的指令移动到哪里。它必须在设置这些样式之后发生,这是在 componentDidMount() 之后发生的。

编辑:我需要更好地澄清我需要它做什么。抱歉之前没有这样做。

必备品

这必须适用于所有常见的桌面和移动设备。

当页面加载时,可能会出现三种情况,具体取决于 #: 后面的 url 中提供的查询

  • 1) 未提供任何查询 - 没有任何反应
  • 2) 提供了有效的查询 - 页面立即滚动到所需的 anchor ,并且页面标题更改为选项的标签
  • 3) 提供了无效的查询 - 查询被输入到搜索框中,搜索框获得焦点,菜单将打开,其中的选项受所提供的查询限制,就像已输入的一样。光标位于查询末尾的搜索框,以便用户可以修改查询。

有效的查询是与选项之一的值匹配的查询。无效查询就是不存在的查询。

浏览器后退和前进按钮应相应地移动滚动位置。

每当从搜索框中选择一个选项时,页面应立即滚动到该 anchor ,查询应清除返回到占位符“搜索...”,网址应更新,文档标题应更改为选项的标签。

可选,但会很棒

做出选择后,菜单关闭,查询返回“搜索...”,或者

  • 搜索框保留焦点,以便用户可以开始输入另一个查询。下次单击时,菜单将打开,并且恢复选择之前的搜索框查询、菜单的过滤器和菜单滚动位置(最首选),或者
  • 搜索框失去焦点。下次获得焦点时,菜单将打开,并且搜索框会在选择之前进行查询,菜单的过滤器和菜单滚动位置将恢复(首选),或者
  • 搜索框保留焦点,以便用户可以开始输入另一个查询。先前的查询和菜单滚动位置丢失。

最佳答案

使用react-scrollable-anchor库可能更容易做到这一点:

import React from "react";
import ReactDOM from "react-dom";
import ScrollableAnchor from "react-scrollable-anchor";

class App extends React.Component {
  render() {
    return (
      <React.Fragment>
        <div style={{ marginBottom: 7000 }}>nothing to see here</div>
        <div style={{ marginBottom: 7000 }}>never mind me</div>
        <ScrollableAnchor id={"doge"}>
          <div>bork</div>
        </ScrollableAnchor>
      </React.Fragment>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

您可以通过此处查看它的工作情况:https://zwoj0xw503.codesandbox.io/#doge

关于reactjs - 如何在加载 React 页面时滚动它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55303221/

相关文章:

reactjs - 改变 api 数据时 react 选择更新值

react-select - 如何在 react-select 中隐藏选项

reactjs - 开 Jest 测试打开 react 选择菜单

javascript - 在react-navigation中,如何防止AppBar固定在顶部?我希望它在我滚动时消失

ios - React Native - 预期参数类型“RCTViewManagerUIBlock”

reactjs - React-redux 在 mapDispatchToProps 中获取 props 或 state

javascript - 如何使用 Redux/Axios 捕获和处理错误响应 422?

javascript - 我可以使用来自 CDN 的 React-Select Async (AsyncSelect) 吗? (我收到 Uncaught ReferenceError : exports is not defined)

reactjs - 使用带有 react-select v2 的搜索图标

javascript - 使用 Angular 2.0 或 React 而不改变我们的构建过程?