【译】React条件渲染

原文连接:www.robinwieruch.de/conditional…
原做者:Robin Wieruchreact

在 React 中使用条件渲染并不困难。在 JSX 中——用于 React 的语法扩展——您可使用纯 JavaScript,其中包括 if else 语句、三元操做符、 switch case 语句等等。在条件渲染中,React 组件根据一个或多个条件决定将返回哪些 DOM 元素。 例如,基于某种逻辑,它能够返回一个项目列表或者一个文本,上面写着“对不起,列表是空的”。当组件具备条件渲染时,渲染的组件外观根据条件不一样而不一样。本文旨在为 React 中的条件渲染和这些模式的最佳实践提供一个详尽的选择清单。函数

目录

  • React条件渲染:if
  • React条件渲染:if else
  • React条件渲染:三元
  • React条件渲染:&&
  • React条件渲染:switch case
  • React多条件渲染
  • React嵌套条件渲染
  • 使用HOC的条件渲染
  • React中的if else组件

React条件渲染:if

React 中最基本的条件渲染逻辑是用一个 if 语句完成的。假设您不想在 React 组件中渲染某些内容,由于它没有必要的 React props 可用。 例如,若是开始没有list的话,React 中的 List 组件不该该在视图中渲染list的HTML元素。 你可使用一个简单的 JavaScript if 语句提早返回(守卫模式) :学习

const users = [
  { id: '1', firstName: 'Robin', lastName: 'Wieruch' },
  { id: '2', firstName: 'Dennis', lastName: 'Wieruch' },
];
function App() {
  return (
    <div>
      <h1>Hello Conditional Rendering</h1>
      <List list={users} />
    </div>
  );
}
function List({ list }) {
  if (!list) {
    return null;
  }
  return (
    <ul>
      {list.map(item => (
        <Item key={item.id} item={item} />
      ))}
    </ul>
  );
}
function Item({ item }) {
  return (
    <li>
      {item.firstName} {item.lastName}
    </li>
  );
}
复制代码

您能够本身尝试将用户设置为 null 或 undefined。 若是props中的信息为 null 或 undefined,则 React 组件在条件渲染中返回 null。 在这里,返回 null 而不是 JSX 的 React 组件将不渲染任何内容。ui

在这个例子中,咱们已经完成了基于 props 的条件渲染,可是条件渲染也能够基于 state 和 hooks 。 注意,咱们尚未在 JSX 内部使用 if 语句,而只是在 return 语句以前在外部使用 if 语句。spa

React条件渲染:if else

让咱们继续前面的例子来学习 React 中的 if else 语句。 若是没有list,咱们就不渲染任何内容,并隐藏 HTML,就像咱们以前用单个 if 语句所看到的那样。 可是,为了得到更好的用户体验,当list为空时,您可能但愿为用户显示一个文本做为反馈。 这将与另外一个 if 语句一块儿使用,可是咱们将用 if else 语句扩展这个例子:code

function List({ list }) {
  if (!list) {
    return null;
  }
  if (!list.length) {
    return <p>Sorry, the list is empty.</p>;
  } else {
    return (
      <div> {list.map(item => ( <Item item={item} /> ))} </div> ); } } 复制代码

如今,List 组件根据一些 JavaScript 逻辑不渲染任何内容、文本或列表。尽管前面的例子展现了如何在 React 中使用 if else 语句,我仍是建议在每次须要保护主返回内容时使用单个 if 语句(这里: 返回列表)做为最佳实践:xml

function List({ list }) {
  if (!list) {
    return null;
  }
  if (!list.length) {
    return <p>Sorry, the list is empty.</p>;
  }
  return (
    <div> {list.map(item => ( <Item item={item} /> ))} </div> ); } 复制代码

这比以前的 if else 条件渲染更具可读性。 全部守卫整齐地排列为主返回语句以前的 if 语句,这也能够解释为隐含的 else 语句。 尽管如此,在 return 语句中尚未使用 if 和 else 语句。对象

React条件渲染:三元

的确,咱们能够在 JSX 中使用 JavaScript,可是在 JSX 中使用 if,else,switch case 这样的语句会变得很困难。 没有真正的方法来内联它。 在 JavaScript 中表达 if else 语句的另外一种方式是三元运算符:教程

// if else
function getFood(isVegetarian) {
  if (isVegetarian) {
    return 'tofu';
  } else {
    return 'fish';
  }
}
// ternary operator
function getFood(isVegetarian) {
  return isVegetarian ? 'tofu' : 'fish';
}
复制代码

例如,假设您的组件显示预览或编辑模式。 条件是一个 JavaScript 布尔值,以 React prop 的形式出现。 你可使用布尔值来决定你想要条件渲染哪一个元素:接口

function Recipe({ food, isEdit }) {
  return (
    <div>
      {food.name}
      {isEdit ? (
        <EditRecipe food={food} />
      ) : (
        <ShowRecipe food={food} />
      )}
    </div>
  );
}
复制代码

三元操做符中两个隐式 return 语句周围的括号()使您可以返回单个或多个 HTML 元素,或从那里返回 React 组件。 若是只有一个元素,能够省略括号。

注意: 有时候你须要用一个 div 元素包裹多行元素做为一个块。 无论怎样,尽可能保持轻量化。 若是()之间包裹的内容太大,能够考虑将其做为组件提取,如示例中所示。

在 React 中使用三元运算渲染不只使条件渲染更加简洁,并且为你在返回中内嵌条件渲染提供了一种简单的方法。 这样,只有一部分 JSX 是有条件地渲染的,而其余部分能够不受任何条件限制地保持完整。

React条件渲染:&&

这种状况常常发生,你想要渲染一个元素或者什么都不渲染。 你已经知道一个简单的if条件能够帮助解决这个问题。 可是,您仍是但愿可以像三元运算符那样内联条件。 使用下面的加载指示符组件,它使用条件三元操做符返回元素或者什么都不返回:

function LoadingIndicator({ isLoading }) {
  return <div>{isLoading ? <p>Loading...</p> : null}</div>;
}
复制代码

这个完成的不错,你在你的 JSX 内联了条件。 然而,还有一种替代方法能够省略返回 null 的必要性。

逻辑 && 运算符能够帮助您使返回 null 的条件更简洁。 在 JavaScript 中,一个 true && Hello World 老是等于 Hello World。 False && Hello World 老是被计算为 false:

const result = true && 'Hello World';
console.log(result);
// Hello World
const result = false && 'Hello World';
console.log(result);
// false
复制代码

在React中,你能够利用这种行为。 若是条件为真,逻辑 && 运算符后面的表达式将做为输出。 若是条件为 false,React 忽略并跳过表达式:

function LoadingIndicator({ isLoading }) {
  return <div>{isLoading && <p>Loading...</p>}</div>;
}
复制代码

当您但愿不返回任何内容或 JSX 中的元素时,这是您的方式。 它也被称为短路求值,这使得它甚至比三元操做符更简洁。

React条件渲染:switch case

如今可能会出现多个条件渲染的状况。 例如,通知组件基于状态字符串渲染错误、警告或信息组件:

function Notification({ text, status }) {
  if (status === 'info') {
    return <Info text={text} />;
  }
  if (status === 'warning') {
    return <Warning text={text} />;
  }
  if (status === 'error') {
    return <Error text={text} />;
  }
  return null;
}
复制代码

您可使用 switch case 操做符来处理多个条件渲染:

function Notification({ text, status }) {
  switch (status) {
    case 'info':
      return <Info text={text} />;
    case 'warning':
      return <Warning text={text} />;
    case 'error':
      return <Error text={text} />;
    default:
      return null;
  }
}
复制代码

对 switch case 操做符使用 default 是明智的,由于 React 组件老是必须返回一个元素或 null。 若是一个组件有一个基于字符串的条件渲染,那么用 TypeScript 来描述组件的接口是有意义的:

type Status = 'info' | 'warning' | 'error';
type NotificationProps = {
  text: string;
  status: Status;
};
function Notification({ text, status }: NotificationProps) {
  switch (status) {
    case 'info':
      return <Info text={text} />;
    case 'warning':
      return <Warning text={text} />;
    case 'error':
      return <Error text={text} />;
    default:
      return null;
  }
}
复制代码

对于多个条件渲染来讲,switch case 写是一个很好的开始。 可是它也有一样的缺点,就像 if else 语句同样。 不能在 JSX 中使用 switch case,对吧? 实际上它能够经过一个条件渲染函数来实现,这个函数是自调用的:

function Notification({ text, status }) {
  return (
    <div>
      {(function() {
        switch (status) {
          case 'info':
            return <Info text={text} />;
          case 'warning':
            return <Warning text={text} />;
          case 'error':
            return <Error text={text} />;
          default:
            return null;
        }
      })()}
    </div>
  );
}
复制代码

能够选择使用条件渲染箭头函数使 switch case 更简洁:

function Notification({ text, status }) {
  return (
    <div>
      {(() => {
        switch (status) {
          case 'info':
            return <Info text={text} />;
          case 'warning':
            return <Warning text={text} />;
          case 'error':
            return <Error text={text} />;
          default:
            return null;
        }
      })()}
    </div>
  );
}
复制代码

总之,switch case 操做符能够帮助您实现多个条件渲染。 可是这是最好的方法吗? 让咱们看看如何用枚举来代替多个条件渲染。

React多条件渲染

带有映射关系的键值对的 JavaScript 对象称为枚举:

const NOTIFICATION_STATES = {
  info: 'Did you know? ...',
  warning: 'Be careful here ...',
  error: 'Something went wrong ...',
};
复制代码

枚举是处理 React 中带有多个条件的条件渲染的一种很好的方法。 它们比 switch case 语句更给力,由于它们能够在 JSX 中使用。 让咱们再次考虑通知组件,但此次使用枚举做为内联对象(内部花括号) :

function Notification({ text, status }) {
  return (
    <div>
      {
        {
          info: <Info text={text} />,
          warning: <Warning text={text} />,
          error: <Error text={text} />,
        }[status]
      }
    </div>
  );
}
复制代码

status 属性键帮助咱们从对象中检索值。 很棒,不是吗? 与 switch case 写操做符相比,它更具可读性。

在本例中,咱们必须使用内联对象,由于对象的值依赖于 text 属性。 不管如何,这是我推荐的方式。 可是,若是它不依赖于 text 属性,你可使用一个枚举做为条件渲染的常量:

const NOTIFICATION_STATES = {
  info: <Info />, warning: <Warning />, error: <Error />, }; function Notification({ status }) { return ( <div> {NOTIFICATION_STATES[status]} </div> ); } 复制代码

这样事情就解决了。 若是咱们仍然依赖以前的 text 属性,咱们可使用一个带有函数的条件渲染来检索值:

const getNotification = text => ({
  info: <Info text={text} />,
  warning: <Warning text={text} />,
  error: <Error text={text} />,
});
function Notification({ status, text }) {
  return <div>{getNotification(text)[status]}</div>;
}
复制代码

毕竟,React 中的枚举条件渲染比 switch case 语句更优雅。 做为枚举的对象提供了大量的选项来实现多个条件渲染。 布尔型的排列也是可能的:

function Message({ isExtrovert, isVegetarian }) {
  const key = `${isExtrovert}-${isVegetarian}`;
  return (
    <div> { { 'true-true': <p>I am an extroverted vegetarian.</p>, 'true-false': <p>I am an extroverted meat eater.</p>, 'false-true': <p>I am an introverted vegetarian.</p>, 'false-false': <p>I am an introverted meat eater.</p>, }[key] } </div>
  );
}
复制代码

最后一个例子有点过头了,我不建议使用它。 然而,当涉及到条件渲染,枚举是我最喜欢的一个React模式。

React嵌套条件渲染

那么在 React 中嵌套条件渲染呢? 是的,这是可能的。 例如,让咱们看看以前的 List 组件,它显示了一个列表、一个空文本或者什么都没有:

function List({ list }) {
  const isNotAvailable = !list;
  const isEmpty = !list.length;
  return (
    <div> {isNotAvailable ? <p>Sorry, the list is not there.</p> : (isEmpty ? <p>Sorry, the list is empty.</p> : <div>{list.map(item => <Item item={item} />)}</div> ) } </div> ); } 复制代码

它能够工做,但我建议避免嵌套条件渲染,由于他们是冗长的,这使得它不太可读。 试试下面的解决方案:

  • 仅在主返回语句以前使用 if 语句的守卫模式
  • 将组件拆分为多个组件,而每一个组件负责本身的非嵌套条件渲染

使用HOC的条件渲染

高阶组件(Higher-Order Components,HOCs)是 React 中条件渲染的完美匹配。 Hoc 能够帮助处理多个使用场景,可是一个场景多是使用条件渲染来改变组件的外观。 让咱们看看一个显示元素或组件的 HOC:

// Higher-Order Component
function withLoadingIndicator(Component) {
  return function EnhancedComponent({ isLoading, ...props }) {
    if (!isLoading) {
      return <Component {...props} />;
    }
    return (
      <div>
        <p>Loading</p>
      </div>
    );
  };
}
const ListWithLoadingIndicator = withLoadingIndicator(List);
function App({ list, isLoading }) {
  return (
    <div>
      <h1>Hello Conditional Rendering</h1>
      <ListWithLoadingIndicator isLoading={isLoading} list={list} />
    </div>
  );
}
复制代码

在这个示例中,List 组件能够专一于渲染列表。 它没必要担忧加载状态。 一个 HOC 在您的实际组件中隐藏了全部的噪音。 最终,您能够添加多个高阶组件(组合) ,以隐藏多个条件渲染边缘状况。 做为 hoc 的替代品,你也可使用 render prop 支持条件渲染。

React中的if else组件

最后但并不是最不重要的是,有外部库处理标记级别上的条件渲染。 他们添加了控制组件,以便在没有 JS 的状况下启用条件渲染:

<Choose>
  <When condition={isLoading}>
    <div><p>Loading...</p></div>
  </When>
  <Otherwise>
    <div>{list.map(item => <Item item={item} />)}</div>
  </Otherwise>
</Choose>
复制代码

不少人认为React(包括JSX)是他们的首选库,由于他们能够在JSX中使用纯HTML和JS处理渲染。

我但愿这个 React 教程对您学习条件渲染有所帮助。 若是你喜欢它,请与你的朋友分享。 最后,我为你准备了一个所有条件渲染的备忘单:

  • if
    • 最基本的条件渲染
    • 用于在一个渲染中提早返回(守卫模式)
    • 不能在 return 语句和 JSX 中使用(自调用函数除外)
  • if-else
    • 不多用它,由于它太冗长了
    • 可使用三元运算符或逻辑 && 运算符替代
    • 不能在 return 语句和 JSX 中使用(自调用函数除外)
  • 三元运算符
    • 用它代替 if-else 语句
    • 它能够在 JSX 和 return 语句中使用
  • 逻辑 && 操做符
    • 当三元运算的一端返回 null 时使用它
    • 它能够在 JSX 和 return 语句中使用
  • switch case
    • 避免使用它,由于它太冗长
    • 能够用枚举替代
    • 不能在 return 语句和 JSX 中使用(自调用函数除外)
  • 枚举
    • 使用它来进行基于多个状态的条件渲染
    • 完美地映射多个条件
  • 嵌套条件渲染
    • 为了可读性,避免使用它们
    • 能够拆分组件、使用 if 语句或者使用 hoc 替代
  • HOCs(高阶组件)
    • 组件能够专一于它们的主要目的
    • 使用 HOC 屏蔽条件渲染
    • 使用多个可组合 hoc 屏蔽多个条件渲染
  • 外部模板组件
    • 避免使用它们,并适应 JSX 和 JS
相关文章
相关标签/搜索