使用React,在以下条件下如何编写更友好,更清晰的条件渲染

时间:2019-11-13 19:19:40

标签: javascript reactjs

在我的React 16应用中,我具有以下渲染功能:

  render() {
    const {
      isLoading,
      leverJobData,
      isApiError
    } = this.state;

    return (
      <Openings.Container>
        <Openings.StyledH4>Open roles:</Openings.StyledH4>

        {isLoading && <h4>Loading...</h4>}

        {!isLoading && isApiError && <h4>Something went wrong. Please try again later!</h4>}

        {!isLoading && !isApiError && leverJobData.length === 0 && (
          <h4>There are no openings at this time.</h4>
        )}

        {!isLoading && !isApiError && leverJobData.length > 0 && (
          <>{this.renderJobOpenings(leverJobData)}</>
        )}
      </Openings.Container>
    );
  }

是否有更干净的方法编写以上内容,还是在React中进行条件渲染的正确方法?

4 个答案:

答案 0 :(得分:2)

当我有这样的障碍时,我喜欢打破条件并确切描述他们在做什么。例如:

render() {
  const {
    isLoading,
    leverJobData,
    isApiError
  } = this.state;

  const hasError = !isLoading && isApiError;
  const noJobsAvailable = !isLoading && !isApiError && leverJobData.length === 0;
  const hasJobsAvailable = !isLoading && !isApiError && leverJobData.length > 0;

  return (
    <Openings.Container>
      <Openings.StyledH4>Open roles:</Openings.StyledH4>
      {isLoading && <h4>Loading...</h4>}
      {hasError && <h4>Something went wrong. Please try again later!</h4>}
      {noJobsAvailable && <h4>There are no openings at this time.</h4>}
      {hasJobsAvailable && this.renderJobOpenings(leverJobData)}
    </Openings.Container>
  );
}

答案 1 :(得分:1)

您还可以考虑包装类似的条件,例如:

const meow = () => {
  const {
    isLoading,
    leverJobData,
    isApiError
  } = this.state;

  return (
    <Openings.Container>
      <Openings.StyledH4>Open roles:</Openings.StyledH4>
      {
        !isLoading ?
          !isApiError ?
            leverJobData.length > 0 ?
              <>{this.renderJobOpenings(leverJobData)}</> :
              <h4>There are no openings at this time.</h4>
            :
              <h4>Something went wrong. Please try again later!</h4>
          : <h4>Loading...</h4>
      }
    </Openings.Container>
  );
}

答案 2 :(得分:-1)

编写此结构最容易理解的方法是使用状态机。这可以通过switch语句来完成:

const IS_LOADING = 1;
const API_ERROR = 2;
const LEVER_JOB_DATA = 3;

_renderStatus = (status) => {
  switch(currentStatus) {
     case LOADING: 
        return <h4>Loading...</h4>;
     case API_ERROR: 
        return <h4>Something went wrong. Please try again later!</h4>;
     case LEVER_JOB_DATA:
        // inside renderJobsOpenings you handle empty state
        const {leverJobData} = this.state;
        return this.renderJobOpenings(leverJobData);
     default:
        // or make sure to render a proper invalid state information
        return null;
    }
}

render() {
    const {currentStatus} = this.state;
    return (
      <Openings.Container>
       { this._renderStatus(currentStatus) }
      </Openings.Container>
    );
  }

避免嵌套三元运算。真的很难阅读。

最好的解决方法是使用useReducer钩子。这样,您可以通过一次副作用调用(setState)在许多接触点上进行适当的状态更改

答案 3 :(得分:-1)

我会做这样的事情:

class MyComponent extends React.Component {
  render = () => {
    const { isLoading, isApiError, leverJobData } = this.state;
    const Content = () => {
      if (isLoading) return <h4>Loading...</h4>;
      else if (isApiError) return <h4>Something went wrong. Please try again later!</h4>;
      else if (leverJobData.length === 0) return <h4>There are no openings at this time.</h4>;
      else if (leverJobData.length > 0) return <h2>{this.renderJobOpenings(leverJobData)}</h2>;
    };
    
    return <Content />
  }
}

这确实增加了组件的额外步骤,但是实际渲染有点“干净”。