首页 > 解决方案 > for 循环内的 setState 无法正确更新状态

问题描述

我有 3 个 div。当我单击特定按钮时,每个人都会激活课程。他们的每个 div 都有一个状态变量,只要它是真的我添加 className='active' 到连接到它的 div :

当我单击按钮时,状态会发生变化,但 div 没有激活类

async activeLang(e) {

  let lang = e.target.getAttribute('lang');

  for (const key in this.state.status) {

    if (key === lang) {
      await this.setState(state => {
        state.status[key] = true
      })
    }else{
      await this.setState(state => {
        state.status[key] = false
      })
    }
  
  }

  console.log(this.state.status);
}

当我将功能更改为此它可以工作:

   activeLang(e) {
    let lang = e.target.getAttribute('lang');

    this.setState({
      status:{
       en: false,
       ar: false,
       fr: false,
      }
    })

    this.setState(state => {
      state.status[lang] = true
    })

    console.log(this.state.status);
  }

=================================================

<ul>
 <li lang="en" onClick={this.activeLang} className={this.state.status.en ? 'active' : '' }>EN</li>
 <li lang="ar" onClick={this.activeLang} className={this.state.status.ar ? 'active' : ''}>AR</li>
 <li lang="fr" onClick={this.activeLang} className={this.state.status.fr ? 'active' : ''}>FR</li>
</ul>

=================================================

<div className={this.state.status.en ? 'to-input en active' : 'to-input en'}>
 <input required type='text' onKeyUp={this.onInputChange} />
 <label title='Category name' placeholder='Ex. Business Cards'></label>
</div>

<div className={this.state.status.ar ? 'to-input ar active' : 'to-input ar'}>
 <input required type='text' onKeyUp={this.onInputChange} />
 <label title='اسم الفئة' placeholder='مثال: كروت العمل'></label>
</div>

<div className={this.state.status.fr ? 'to-input fr active' : 'to-input fr'}>
 <input required type='text' onKeyUp={this.onInputChange} />
 <label title='Nom de catégorie' placeholder='Ex. Cartes de visite'></label>
</div>

图。1

标签: javascriptreactjsweb

解决方案


不要循环执行。只需调用一次:

const lang = e.target.getAttribute('lang');
this.setState(state => ({
   ...state,
   status: Object.keys(state.status).reduce((acc,key) => ({
     ...acc,
     [key]:state.status[key] === lang // set all statuses to false except for `lang`
   }),{});
});

编辑:

此外,setState不返回承诺,你不能await。它确实接受回调,但这不是最好的解决方案(见上文)。

你永远不应该setState循环调用,会发生混乱的事情。

编辑#2:

从外观上看,我为您的状态提供了更好的解决方案。一次只能有一个语言处于活动状态,因此您不需要status- 您只需要知道激活的语言是什么,因此:

const state = { activatedLang: 'en' } // or 'fr' or 'ar'

然后你可以这样做:

this.setState({ activatedLang: e.target.getAttribute('lang') });

推荐阅读