react-fullpage - 避免渲染中的 setState 无限循环

react-fullpage - avoid setState infinite loop in render

TLDR 问题:基本上我想在页脚打开时隐藏 sidenav 按钮。

在我的 App.js 中,我正在呈现导航和 react-fullpage(滚动到部分组件)并传递 isFooterOpen 状态和更改它的方法。

App.js

class App extends Component {
  state = { isFooterOpen: false };
  show = () => { this.setState({ isFooterOpen: true }); };
  hide = () => { this.setState({ isFooterOpen: false }); };

  render() {
    return (
      <React.Fragment>
        <Navigation
          isFooterOpen={this.state.isFooterOpen}
          hide={this.hide}
          show={this.show}
        />

        <FullPageWrapper
           isFooterOpen={this.state.isFooterOpen}
           hide={this.hide}
           show={this.show}
           {...fullpageOptions}
        />              
      </React.Fragment>
    );
  }
}

导航将状态向下传递到侧边按钮,我 show/hide 它基于它,工作正常。

问题是当我想从我的 FullpageWrapper 触发状态更改时,我正在检测我是滚动到上一节还是从上一节向上滚动。

组件正在使用渲染道具,所以基本上我在渲染中调用 setState,它会导致无限循环,但我找不到访问该状态(方向、索引等)的解决方法。甚至 toggleFooter 函数也感觉有点 "hacky" 因为我正在为那个状态对象设置属性,而不是用 npm ReactFullpage 组件以某种方式保持我自己的状态。

FullpageWrapper.js

function toggleFooter(state, props) {
  if (state.callback === "onLeave") {
    if (state.direction === "down") {
      const emptySection = document.querySelector("#empty");
      if (emptySection.classList.contains("active")) {
        state.isFooterOpen = true;
        // props.show(); // change app state and hide side button - infinite loop here
      }
    } else if (state.direction === "up" && state.origin.index === 5) {
      state.isFooterOpen = false;
      // props.hide(); // change app state and hide side button - infinite loop here
    }
  }
}

const FullPageWrapper = fullpageProps => (
  <ReactFullpage
    {...fullpageProps}
    render={({ state, fullpageApi }) => {
      toggleFooter(state, fullpageProps);

      return (
        <div style={{ position: "relative" }}>
          <HeroSection />
          <AboutSection />
          <TeamSection />
          <ServicesSection />
          <ContactSection />
          <Empty />    
          <Footer isFooterOpen={state.isFooterOpen} />
        </div>
      );
    }}
  />
);

我也尝试了简单的事件总线,我从 FullpageWrapper 发送了一个事件,但我仍然从渲染器发送它,所以这是同样的问题...

我删除了所有不必要的内容,这里是 codesandbox 示例。

如果用 if 语句包装 setState 调用,我猜这会消除无限循环吗?

我在这里创建了一个更新的代码沙箱,看起来它的功能与您设计的一样:

https://codesandbox.io/s/p39w4z51pq

show = () => { if(!this.state.isFooterOpen) { this.setState({ isFooterOpen: true }); } }; hide = () => { if(this.state.isFooterOpen) { this.setState({ isFooterOpen: false }); } };