简体   繁体   中英

react-fullpage - avoid setState infinite loop in render

TLDR Question: Basically i want to hide sidenav button when the footer is open.

In my App.js i am rendering the navigation and react-fullpage (scroll to section component) and passing the isFooterOpen state and methods that change it.

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>
    );
  }
}

Navigation passes down the state to the sideButton where i show/hide it based on it, which works fine.

Problem is when i want to trigger that state change from my FullpageWrapper where i am detecting whether i am scrolling past last section or scrolling up from the last section.

Component is using render props so basically i am calling setState there in render and it causes infinite loop which i get but i can't find a workaround to access that state (direction, index and so on). Even toggleFooter function feels a bit "hacky" because i am setting properties to that state object instead of somehow keeping my own state with that npm ReactFullpage component.

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>
      );
    }}
  />
);

I tried also simple event Bus where i dispatch an event from FullpageWrapper but i am still dispatching it from render so it's the same problem...

I stripped out everything unnecessary and here is the codesandbox example.

If you wrap your setState calls with an if statement, I'd guess that that would remove the infinite loop?

I've created an updated code sandbox here, and it looks like it functions as you've designed:

https://codesandbox.io/s/p39w4z51pq

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM