不嵌套三元表达式-替代

时间:2019-02-07 09:00:29

标签: javascript reactjs

我有这个React组件,它可以有4种状态:advisoryResults,results,noResults和newAccount。

我认为使用三元表达式来这样做是有道理的,但这是不允许的,对此有什么好的选择?

export default class Home extends React.Component {
  state = {
    isAdmin: false
  };

  render() {
    const { isAdmin } = this.state;
    return (
      <div>
        <Header />
        <div css={innerWrap}>
          {isAdmin ? (
            <Button
              onClick={this.handleAddNewContact }
            >
              Add new Contact
            </Button>
          ) : (
            ''
          )}
   {searchMode === searchModes.advisoryPanels ? (
            <>
              <SearchAdvisoryPanels />
              <div css={{ textAlign: 'center', margin: '60px auto' }}>
                <ManAtDesk />
              </div>
            </>
          ) : searchMode === searchModes.noResultsPanel ? (
            <SearchNoResultsPanel />
          ) : searchMode === searchModes.resultsPanel ? (
            accountInfo.map((info, index) => (
              <SearchResultPanel info={info} isAdmin={isAdmin} key={index} />
            ))
          ) : searchMode === searchModes.addContactPanel ? (
            <AddNewContactForm
              onCancelAccount={this.onCancelAccount}
              onSaveAccount={this.onSaveAccount}
            />
          ) : null}
        </div>
      </div>
    );
  }
}

请告知。

3 个答案:

答案 0 :(得分:2)

我建议做这样的事情:

export default class Home extends React.Component {
  state = {
    isAdmin: false
  };

  onCancelAccount = () => {};
  onSaveAcciont = () => {};

  renderSearchResults = (searchMode) => {
    const { info, isAdmin, index } = this.props;

    switch (searchMode) {
      case searchModes.advisoryPanels:
        return this.renderAdvisoryPanels();
      case searchModes.noResultsPanel:
        return <SearchNoResultsPanel />;
      case searchModes.resultsPanel:
        return <SearchResultPanel info={info} isAdmin={isAdmin} key={index} />;
      case searchModes.addContactPanel:
        return (
          <AddNewContactForm
            onCancelAccount={this.onCancelAccount}
            onSaveAccount={this.onSaveAccount}
          />
        );
      default:
        return null;
    }
  }

  renderAdvisoryPanels = () => (
    <React.Fragment>
      <SearchAdvisoryPanels />
      <div css={{ textAlign: 'center', margin: '60px auto' }}>
        <ManAtDesk />
      </div>
    </React.Fragment>
  );

  render() {
    const { isAdmin } = this.state;

    return (
      <div>
        <Header />
        <div css={innerWrap}>
          {isAdmin && (
            <Button onClick={this.handleAddNewContact}>Add new Contact</Button>
          )}
          {this.renderSearchResults(searchMode)}
        </div>
      </div>
    );
  }
}

某些处理程序/道具在您的示例中无法立即看到,因此,如果我遇到问题,请解决。

答案 1 :(得分:0)

当您用switch语句问这个问题时,我正要写一个答案。

使用包含所有可能结果的JSON可以解决您的问题,而无需添加不必要的代码:

render() {
    const { isAdmin } = this.state;
    return (
        <div>
            <Header />
            <div css={innerWrap}>
                {isAdmin && <Button onClick={this.handleAddNewContact}> Add new Contact</Button>}
                {
                    {
                        [searchModes.SearchAdvisoryPanels]: (
                            <>
                                <SearchAdvisoryPanels />
                                <div css={{ textAlign: 'center', margin: '60px auto' }}>
                                    <ManAtDesk />
                                </div>
                            </>
                        ),
                        [searchModes.noResultsPanel]: <SearchNoResultsPanel />,
                        [searchModes.resultsPanel]: accountInfo.map((info, index) => (<SearchResultPanel info={info} isAdmin={isAdmin} key={index} />)),
                        [searchModes.addContactPanel]: <AddNewContactForm  onCancelAccount={this.onCancelAccount} onSaveAccount={this.onSaveAccount} />
                    }[searchMode]
                }
            </div>
        </div>
    );
}

但是,即使未显示所有组件,此解决方案也将安装所有组件,而使用箭头功能可以通过仅安装所需组件来提高性能:

render() {
    const { isAdmin } = this.state;
    return (
        <div>
            <Header />
            <div css={innerWrap}>
                {isAdmin && <Button onClick={this.handleAddNewContact}> Add new Contact</Button>}
                {
                    {
                        [searchModes.SearchAdvisoryPanels]: () => (
                            <>
                                <SearchAdvisoryPanels />
                                <div css={{ textAlign: 'center', margin: '60px auto' }}>
                                    <ManAtDesk />
                                </div>
                            </>
                        ),
                        [searchModes.noResultsPanel]: () => <SearchNoResultsPanel />,
                        [searchModes.resultsPanel]: () => accountInfo.map((info, index) => (<SearchResultPanel info={info} isAdmin={isAdmin} key={index} />)),
                        [searchModes.addContactPanel]: () => <AddNewContactForm  onCancelAccount={this.onCancelAccount} onSaveAccount={this.onSaveAccount} />
                    }[searchMode]()
                }
            </div>
        </div>
    );
}

编辑

如果变量的值可以不同于每个给定的选项,则可以实现以下解决方案。

如果值未定义,则发送不执行任何操作的函数:

}[searchMode] || (x => x)()

或将结果存储在返回值之外,并调用该函数(如果存在):

render() {
    const { isAdmin } = this.state;
    const searchRender = {
        [searchModes.SearchAdvisoryPanels]: () => (
            <>
                <SearchAdvisoryPanels />
                <div css={{ textAlign: 'center', margin: '60px auto' }}>
                    <ManAtDesk />
                </div>
            </>
        ),
        [searchModes.noResultsPanel]: () => <SearchNoResultsPanel />,
        [searchModes.resultsPanel]: () => accountInfo.map((info, index) => (<SearchResultPanel info={info} isAdmin={isAdmin} key={index} />)),
        [searchModes.addContactPanel]: () => <AddNewContactForm onCancelAccount={this.onCancelAccount} onSaveAccount={this.onSaveAccount} />
    }[searchMode]

    return (
        <div>
            <Header />
            <div css={innerWrap}>
                {isAdmin && <Button onClick={this.handleAddNewContact}> Add new Contact</Button>}
                {searchRender && searchRender()}
            </div>
        </div>
    );
}

编辑:这是什么黑魔法?

第一步是使用computed properties创建JSON,它允许您从变量而不是硬编码值中分配对象键:

const searchModes = {
    SearchAdvisoryPanels: "a",
    noResultsPanel: "b",
    resultsPanel: "c",
    addContactPanel: "d"
}

const result = {
    [searchModes.SearchAdvisoryPanels]: 1,
    [searchModes.noResultsPanel]: 2 ,
    [searchModes.resultsPanel]: 3,
    [searchModes.addContactPanel]: 4
}

console.log(result)

我们现在可以将1 2 3 4替换为所需的值。在这种情况下,箭头起作用。要获得所需的结果,只需在JSON的末尾添加大括号:

const searchModes = {
    SearchAdvisoryPanels: "a",
    noResultsPanel: "b",
    resultsPanel: "c",
    addContactPanel: "d"
}

const search = "c"

const result = {
    [searchModes.SearchAdvisoryPanels]: 1,
    [searchModes.noResultsPanel]: 2 ,
    [searchModes.resultsPanel]: 3,
    [searchModes.addContactPanel]: 4
}[search]

console.log(result)

如果将返回的值转换为函数,则只需在其末尾加上括号即可:

const searchModes = {
    SearchAdvisoryPanels: "a",
    noResultsPanel: "b",
    resultsPanel: "c",
    addContactPanel: "d"
}

const search = "c"

const result = {
    [searchModes.SearchAdvisoryPanels]: () => 1,
    [searchModes.noResultsPanel]: () => 2 ,
    [searchModes.resultsPanel]: () => 3,
    [searchModes.addContactPanel]: () => 4
}[search]()

console.log('Short : ' + result)

//Long syntax :

const options = {
    [searchModes.SearchAdvisoryPanels]: () => 1,
    [searchModes.noResultsPanel]: () => 2 ,
    [searchModes.resultsPanel]: () => 3,
    [searchModes.addContactPanel]: () => 4
}

const action = options[search]

const output = action()

console.log('Long : ' + output)

答案 2 :(得分:0)

这是您应该在JS上进行的工作,然后将内容移动到fn。这种方法使渲染fn保持清晰。您的getSearchMode读数清晰,没有复杂的动作。您不会设置不必要的对象,不会在渲染函数内创建许多函数,也不会做任何魔术-只是普通的旧JS。

export default class Home extends React.Component {
  state = {
    isAdmin: false,
  }

  getSearchMode = (searchMode) => {
    if (searchMode === searchModes.advisoryPanels) {
      return (
        <>
          <SearchAdvisoryPanels />
          <div css={{ textAlign: 'center', margin: '60px auto' }}>
            <ManAtDesk />
          </div>
        </>
      )
    }
    if (searchMode === searchModes.noResultsPanel) {
      return <SearchNoResultsPanel />
    }
    if (searchMode === searchModes.resultsPanel) {
      return accountInfo.map((info, index) => (
        <SearchResultPanel info={info} isAdmin={this.state.isAdmin} key={index} /> // you should not use index as key
      ))
    }
    if (searchMode === searchModes.addContactPanel) {
      return (
        <AddNewContactForm
          onCancelAccount={this.onCancelAccount}
          onSaveAccount={this.onSaveAccount}
        />
      )
    }
    return null
  }

  render() {
    const { isAdmin } = this.state
    return (
      <div>
        <Header />
        <div css={innerWrap}>
          {isAdmin ? <Button onClick={this.handleAddNewContact}>Add new Contact</Button> : ''}
          {this.getSearchMode(searchMode)}
        </div>
      </div>
    )
  }
}