【问题标题】:How to avoid code repetition for 3 similar buttons in React?如何避免 React 中 3 个类似按钮的代码重复?
【发布时间】:2019-07-12 15:34:23
【问题描述】:

我有 3 个用于 3 种不同语言的按钮,

用户可以选择显示哪种语言文本:

  1. “德国德语”

  2. “法国法语”

  3. “英文”

// This is state of component:
 state = {
    translationOptions: {
      german: false,
      french: false,
      english: true
    }
  };

// This is function which change the language

  <button
    className={`doc-translation-btn ${german ? 'active-background-color' : ''}`}
    onClick={() => this.changeDocumentLanguage('german')}
  >
     DE
  </button>

  <button
    className={`doc-translation-btn ${french ? 'active-background-color' : ''}`}
    onClick={() => this.changeDocumentLanguage('french')}
    >
      FR
   </button>

  <button
     className={`doc-translation-btn ${english ? 'active-background-color' : '' }`}
     onClick={() => this.changeDocumentLanguage('english')}>
       EN
   </button>

如何优化这段代码?

【问题讨论】:

  • 如何创建一个函数来循环translationOptions并动态生成每个按钮?

标签: javascript reactjs


【解决方案1】:
const langs = [{name: 'German', abbr: 'GE'}, {name: 'French', abbr: 'FR'}, 
{name: 'English', abbr: 'EN'}]


//// Assuming React Stateful Component

state = {
   translationOption: ''  //Will be of of German, French, or English on state change
}

////

render() {
    return (
      <div>
        {langs.map(({ name, abbr }) => (
          <button
            className={`doc-translation-btn ${name === 
            this.state.translationOption ? 'active-background-color' : '' }`}
            onClick={() => this.setState({ translationOption: name })>
           {abbr}
         </button>
        )}
    </div>
  )
}

注意:如果您想使用单独的布尔属性(无论是嵌套的还是其他方式)处理适用的翻译语言,您需要考虑在另一个属性为 false 时将其他属性切换为 false在您的状态处理程序方法中设置为 true(假设一次只能应用一种翻译)。这样的方法可以工作:

  handleLangChange = selectedLang => {
    const { translationOptions: oldOpts } = this.state;
    const translationOptions = Object.keys(oldOpts).reduce((acc, cur) => {
       return { ...acc, [cur]: cur === selectedLang };
     }, {})

     this.setState({ ...this.state, translationOptions });
   }

【讨论】:

  • 这种方式不管理语言的短形式。 EN,FR,DE
  • 为疏忽道歉 - 已修复 :)
  • 嗯?比较就在那里,并且在您的笔记之前就已经存在
【解决方案2】:

您可以创建一个函数renderButtons,在其中创建对象数组,然后将map() 设置为按钮。

renderButtons(){
   let btns = [
        {name: 'german', short: 'DE'}
        //... same for others.
   ]
   return btns.map(({name, short}) => (
      <button
    className={`doc-translation-btn ${this.state.translationOptions[name] ? 'active-background-color' : ''}`}
    onClick={() => this.changeDocumentLanguage(name)}
  >
     {short}
  </button>
   ))
} 

render() 方法中,只需在需要按钮的地方调用此方法即可。

render(){
    return (
       <div>{this.renderButtons()}</div>
    )
}

【讨论】:

    【解决方案3】:

    根据用例,您还可以为此创建一个新组件:

     const LangButton = ({ active, name, abbr }) =>
      <button className={`doc-translation-btn ${active ? 'active-background-color' : ''}`}  onClick={() => this.changeDocumentLanguage(name)}>{abbr}</button>;
    
     return <div>
       <LangButton active={german} name="german" abbr="DE" />
       ...
     </div>;
    

    【讨论】:

      【解决方案4】:

      使用数组:

      const langDef = [
        { key: 'german', label: 'DE' },
        ...
      ]
      
      const buttons = langDef.map(({ key, label })=>
        <button
          className={`doc-translation-btn ${this.state.translationOptions[key] ? 'active-background-color' : ''}`}
          onClick={() => this.changeDocumentLanguage(key)}
        >
           {label}
        </button>
      )
      
      return <div className="my-awesome-language-selector">{buttons}</div>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-29
        相关资源
        最近更新 更多