簡體   English   中英

如何停止對組件進行無限重渲染

[英]How to stop react component from infinite re-render

我想在我的應用程序中使用js-cookie,但是當我獲得cookie時,我的組件會不斷重新渲染,直到瀏覽器崩潰為止。

我得到的錯誤是:setState(...):在現有狀態轉換期間無法更新...

我剛剛使用了shouldComponentUpdate,但它導致click事件無法正常工作。

shouldComponentUpdate(nextProps, nextState) 
{
    return nextState.language != this.state.language;
}

有誰知道其他解決方案,而不是組件更新來阻止組件無限重新渲染嗎?

class MainLayout extends Component {
  constructor(props) {
    super(props);
    console.log('constructor');
    this.state = {
      sideBarOpen: false,
      languages: getStoreLanguages,
      language: Cookies.get('langCode')
    }
  }

  componentWillMount() {
    this.props.langCode();
    this.props.defaultLangCode();
  }

  componentDidMount() {
    $('.dropdown-toggle').megaMenu && $('.dropdown-toggle').megaMenu({ container: '.mmd' });
  }

  shouldComponentUpdate(nextProps, nextState) {
    return nextState.language != this.state.language;
  }

  toggleSidebar = () => {
    this.setState({
      sideBarOpen: !this.state.sideBarOpen,
    });
  }

  overlayClickHandler = () => {
    this.setState({
      sideBarOpen: false,
    });
  }

  handleLanguage = (langCode) => {
    if (Cookies.get('langCode')) {
      return Cookies.get('langCode');
    } else {
      Cookies.set('langCode', langCode, { expires: 7 });
      return langCode;
    }
  }

  render() {
    let overlay = { display: this.state.sideBarOpen ? 'block' : 'none' };
    const langCode = this.handleLanguage(this.props.params.id);
    const isDefaultLang = isDefaultLanguage(langCode);
    const isValidLang = isValidLanguage(langCode);

    if (langCode && !isValidLang) {
      this.props.router.push(`/${langCode}/error`);
    }

    if (langCode && isValidLang) {
      const path = getLocalisedPath(langCode, isDefaultLang)
      this.props.router.push("/" + path);
    }

    return (
      <div>
        <Helmet>
          <script type="application/ld+json">{structuredData()}</script>
        </Helmet>
        <TokenManager>
          {(state, methods) => (
            <div>
              <WithHelmet {...this.props} />
              <WithUserHeaderInfo {...this.props} />
              <WithStoreDetail />
              <WithDataLayerStoreDetail />
              <header className='header__nav'>
                <NavbarManagerWillHideOnEditor
                  sideBarOpen={this.state.sideBarOpen}
                  toggleSidebar={this.toggleSidebar}
                  languages={this.state.languages}
                  {...this.props}
                />
                <div
                  className="mmm__overlay"
                  onClick={this.overlayClickHandler}
                  style={overlay}
                />
                <div
                  className="mmm__overlay--hidenav"
                  onClick={this.overlayClickHandler}
                  style={overlay}
                />
              </header>
              <main>{this.props.children}</main>
              <Modal modalId="modal-account" size="md">
                {(closeModal) => (
                  <Auth
                    closeModal={closeModal} />
                )}

              </Modal>
              {!this.props.location.pathname.startsWith('/checkout') && <FooterWillHideOnEditor languages={this.state.languages}/>}
            </div>
          )
          }
        </TokenManager>
      </div>
    );
  }
}

const mapDispatchToProps = (dispatch, value) => {
  const langCode = Cookies.get('langCode') || value.params.id;
  const defaultLang = getDefaultLanguage();
  const isDefault = isDefaultLanguage(langCode);
  const isValid = isValidLanguage(langCode);
  const lang = !isValid || isDefault ? defaultLang : langCode;

  return {
    langCode: () => dispatch({ type: 'SET_LANGUAGE', payload: lang }),
    defaultLangCode: () => dispatch({ type: 'SET_DEFAULT_LANGUAGE', payload: defaultLang })
  }
}

export default connect(null, mapDispatchToProps)(MainLayout);

我發現了組件繼續重新渲染的原因,實際上是由於以下條件造成的:

if (langCode && isValidLang) {
    const path = getLocalisedPath(langCode, isDefaultLang)
    this.props.router.push("/" + path);
}

這始終是正確的,並且獲取路徑並推送到導致組件重新渲染的路徑。

謝謝

let overlay = { display: this.state.sideBarOpen ? 'block' : 'none' };
const langCode = this.handleLanguage(this.props.params.id);
const isDefaultLang = isDefaultLanguage(langCode);
const isValidLang = isValidLanguage(langCode);

if (langCode && !isValidLang) {
  this.props.router.push(`/${langCode}/error`);
}

if (langCode && isValidLang) {
  const path = getLocalisedPath(langCode, isDefaultLang)
  this.props.router.push("/" + path);
}

這里的代碼重置了再次分派的state /或mapDispatchToProps。這就是為什么要重新渲染。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM