react 模式_React中不断发展的模式

react 模式

Let’s take a closer look at some of the patterns that are emerging in the React ecosystem. These patterns improve readability, code clarity, and push your code towards composition and reusability.

让我们仔细看看React生态系统中出现的一些模式。 这些模式提高了可读性,代码清晰度,并将您的代码推向了组合和可重用性。

I started working with React roughly about 3 years ago. At that time, there were no established practices from which to learn in order to leverage its capabilities.

我大约在3年前开始与React合作。 当时,尚没有可借鉴的实践来利用其功能。

It took about 2 years for the community to settle around a few ideas. We shifted from React.createClass to the ES6 class and pure functional components. We dropped mixins and we simplified our APIs.

社区花了大约2年时间解决了一些想法。 我们从React.createClass转移到ES6 class和纯功能组件。 我们删除了mixins,并简化了API

Now as the community is larger than ever, we’re starting to see a couple of nice patterns evolving.

现在,随着社区比以往任何时候都更大,我们开始看到一些不错的模式正在演变

In order to understand these patterns you need a basic understanding of the React concepts and its ecosystem. Please note, however, that I will not cover them in this article.

为了理解这些模式,您需要对React概念及其生态系统有基本的了解。 但是请注意,我将不在本文中介绍它们。

So let’s begin!

让我们开始吧!

有条件的渲染 (Conditional Render)

I’ve seen the following scenario in a lot of projects.

我已经在许多项目中看到以下情形。

When people think of React and JSX, they still think in terms of HTML and JavaScript.

当人们想到ReactJSX时 ,他们仍然会想到HTMLJavaScript

So the natural step is to separate the conditional logic from the actual return code.

所以自然的一步是分离 实际返回码中的条件逻辑。

const condition = true;

const App = () => {
  const innerContent = condition ? (
    <div>
      <h2>Show me</h2>
      <p>Description</p>
    </div>
  ) : null;
  
  return (
    <div>
      <h1>This is always visible</h1>
      { innerContent }
    </div>
  );
};

This tends to get out of control, with multiple ternaries at the beginning of each render function. You constantly have to jump inside the function to understand when a certain element is rendered or not.

这往往会失去控制,在每个render函数的开头都有多个三元组 。 您经常需要跳入函数内部,以了解何时呈现或不呈现某个元素。

As an alternative, try the following pattern, where you benefit from the execution model of the language.

或者,尝试以下模式,您将从语言的执行模型中受益。

const condition = true;

const App = () => (
  <div>
    <h1>This is always visible</h1>
    {
      condition && (
        <div>
          <h2>Show me</h2>
          <p>Description</p>
        </div>
      )
    }
  </div>
);

If condition is false, the second operand of the && operator is not evaluated. If it is true, the second operand — or the JSX we wish to render — is returned.

如果condition为假,则不评估&&运算符的第二个操作数。 如果为true,则返回第二个操作数( 或我们希望呈现的JSX)

This allows us to mix UI logic with the actual UI elements in a declarative way!

这允许我们以声明的方式 UI逻辑与实际的UI元素混合

Treat JSX like it’s an integral part of your code! After all, it’s just JavaScript.

将JSX视为代码不可或缺的一部分! 毕竟,它只是JavaScript

传递道具 (Passing Down Props)

When your application grows, you have smaller components that act as containers for other components.

随着应用程序的增长,您将拥有较小的组件,这些组件可以充当其他组件的容器。

As this happens, you need to pass down a good chunk of props through a component. The component doesn’t need them, but its children do.

发生这种情况时,您需要通过组件传递大量的道具。 该组件不需要它们,但其子组件则需要它们。

A good way of bypassing this is to use props destructuring together with JSX spread, as you can see here:

绕过此问题的一种好方法是将props 分解JSX spread一起使用,如您在此处看到的:

const Details = ( { name, language } ) => (
  <div>
    <p>{ name } works with { language }</p>
  </div>
);

const Layout = ( { title, ...props } ) => (
  <div>
    <h1>{ title }</h1>
    <Details { ...props } />
  </div>
);

const App = () => (
  <Layout 
    title="I'm here to stay"
    language="JavaScript"
    name="Alex"
  />
);

So now, you can change the props needed for Details and be sure that those props are not referenced in multiple components.

因此,现在,您可以更改Details所需的道具,并确保没有在多个组件中引用这些道具。

破坏道具 (Destructuring Props)

An app changes over time, and so do your components. A component you wrote two years ago might be stateful, but now it can be transformed into a stateless one. The other way around also happens a lot of times!

应用会随着时间而变化,您的组件也会随之变化。 您两年前编写的组件可能是有状态的,但现在可以将其转换为无状态的组件。 相反,很多次也发生!

Since we talked about props destructuring, here’s a good trick I use to make my life easier on the long run. You can destructure your props in a similar manner for both types of components, as you can see below:

自从我们谈论道具销毁以来,从长远来看,这是一个使我的生活更轻松的好技巧。 您可以对两种类型的组件以类似的方式来分解道具,如下所示:

const Details = ( { name, language } ) => (
  <div>
    <p>{ name } works with { language }</p>
  </div>
);

class Details extends React.Component {
  render() {
    const { name, language } = this.props;
    return (
      <div>
        <p>{ name } works with { language }</p>
      </div>
    )
  }
}

Notice that lines 2–4 and 11–13 are identical. Transforming components is much easier using this pattern. Also, you limit the usage of this inside the component.

请注意,第2–4行和第11–13相同的。 使用此模式转换组件要容易得多。 此外,你限制的使用this组件里。

提供者模式 (Provider Pattern)

We looked at an example where props need to be sent down through another component. But what if you have to send it down 15 components?

我们看了一个示例,其中需要通过另一个组件向下发送道具。 但是,如果您必须将其发送给15个组件怎么办?

Enter React Context!

输入React Context

This is not necessarily the most recommended feature of React, but it gets the job done when needed.

这不一定是React最推荐的功能,但是可以在需要时完成工作。

It was recently announced that the Context is getting a new API, which implements the provider pattern out of the box.

最近宣布 ,Context正在获得一个新的API,该API开箱即用地实现了提供程序模式

If you are using things like React Redux or Apollo, you might be familiar with the pattern.

如果您正在使用React ReduxApollo之类的东西,您可能会熟悉该模式。

Seeing how it works with today’s API will help you understand the new API as well. You can play around with the following sandbox.

了解它如何与当今的API一起使用,还将帮助您理解新的API。 您可以使用以下沙箱进行游戏。

The top level component — called Provider — sets some values on the context. The child components — called Consumers — will grab those values from the context.

顶层组件(称为提供程序)在上下文中设置一些值。 子组件(称为“ 消费者” )将从上下文中获取这些值。

The current context syntax is a bit strange, but the upcoming version is implementing this exact pattern.

当前的上下文语法有点奇怪,但是即将发布的版本正在实现这种确切的模式。

高阶组件 (High Order Components)

Let’s talk about reusability. Together with dropping the old React.createElement() factory, the React team also dropped the support for mixins. They were, at some point, the standard way of composing components through plain object composition.

让我们谈谈可重用性。 React.createElement()删除旧的React.createElement()工厂之外,React团队还删除了对mixins的支持。 在某些时候,它们是通过简单的对象组合来构成组件的标准方法。

High Order Components — HOCs from now on — went out to fill the need for reusing behavior across multiple components.

高阶组件 (即从现在开始的HOC)消失了,以满足跨多个组件重用行为的需求。

A HOC is a function that takes an input component and returns an enhanced/modified version of that component. You will find HOCs under different names, but I like to think of them as decorators.

HOC是接受输入组件并返回该组件的增强/修改版本的函数。 您会发现名称不同的HOC,但我想将它们视为装饰器

If you are using Redux, you will recognize that the connect function is a HOC — takes your component and adds a bunch of props to it.

如果您使用的是Redux,您将认识到connect函数是一个HOC,即使用您的组件并为其添加了一些道具

Let’s implement a basic HOC that can add props to existing components.

让我们实现一个基本的HOC,该HOC可以向现有组件添加道具。

const withProps = ( newProps ) => ( WrappedComponent ) => {
  const ModifiedComponent = ( ownProps ) => ( // the modified version of the component
    <WrappedComponent { ...ownProps } { ...newProps } /> // original props + new props
  );

  return ModifiedComponent;
};

const Details = ( { name, title, language } ) => (
  <div>
    <h1>{ title }</h1>
    <p>{ name } works with { language }</p>
  </div>
);

const newProps = { name: "Alex" }; // this is added by the hoc
const ModifiedDetails = withProps( newProps )( Details ); // hoc is curried for readability

const App = () => (
  <ModifiedDetails 
    title="I'm here to stay"
    language="JavaScript"
  />
);

If you like functional programming, you will love working with high order components. Recompose is a great package that gives you all these nice utility HOCs like withProps, withContext, lifecycle, and so on.

如果您喜欢函数式编程,那么您将喜欢使用高阶组件。 Recompose是一个很棒的软件包,它为您提供所有这些不错的实用程序withContext ,例如withPro pswithContextlifecycle等。

Let’s have a look at a very useful example of reusing functionality.

让我们看一个非常有用的重用功能性示例。

function withAuthentication(WrappedComponent) {
  const ModifiedComponent = (props) => {
    if (!props.isAuthenticated) {
      return <Redirect to="/login" />;
    }

    return (<WrappedComponent { ...props } />);
  };

  const mapStateToProps = (state) => ({
    isAuthenticated: state.session.isAuthenticated
  });

  return connect(mapStateToProps)(ModifiedComponent);
}

You can use withAuthentication when you want to render sensitive content inside a route. That content will only be available to logged-in users.

当您要在路线内呈现敏感内容时,可以使用withAuthentication 。 该内容仅对登录用户可用。

This is a cross-cutting concern of your application implemented in a single place and reusable across the entire app.

这是您的应用程序在一个地方实现并在整个应用程序中可重用的跨领域关注点。

However, there is a downside to HOCs. Each HOC will introduce an additional React Component in your DOM/vDOM structure. This can lead to potential performance problems as your application scales.

但是,HOC有一个缺点。 每个HOC都会在您的DOM / vDOM结构中引入一个额外的React组件。 随着应用程序的扩展,这可能导致潜在的性能问题。

Some additional problems with HOCs are summarized in this great article by Michael Jackson. He advocates replacing HOCs with the pattern we’ll be talking about next.

迈克尔·杰克逊 ( Michael Jackson)这篇出色的文章中总结了HOC的其他一些问题。 他主张用我们接下来要讨论的模式替换HOC。

渲染道具 (Render Props)

While it is true that render props and HOCs are interchangeable, I don’t favor one over another. Both patterns are used to improve reusability and code clarity.

虽然渲染道具HOC确实是可以互换的,但我并不偏爱另一个。 两种模式都用于提高可重用性和代码清晰度。

The idea is that you yield the control of your render function to another component that then passes you back the control through a function prop.

我们的想法是,你得到你的渲染功能的控制到另一个组件,然后使你通过一个功能道具背控制。

Some people prefer to use a dynamic prop for this, some just use this.props.children.

有些人喜欢为此使用动态道具 ,有些人只是使用this.props.children

I know, it’s still very confusing, but let’s see a simple example.

我知道,这仍然很令人困惑,但是让我们看一个简单的例子。

class ScrollPosition extends React.Component {
  constructor( ) {
    super( );
    this.state = { position: 0 };
    this.updatePosition = this.updatePosition.bind(this);
  }
  
  componentDidMount( ) {
    window.addEventListener( "scroll", this.updatePosition );
  }

  updatePosition( ) {
    this.setState( { position: window.pageYOffset } )
  }

  render( ) {
    return this.props.children( this.state.position )
  }
}

const App = () => (
  <div>
    <ScrollPosition>
      { ( position ) => (
        <div>
          <h1>Hello World</h1>
          <p>You are at { position }</p>
        </div>
      ) }
    </ScrollPosition>
  </div>
);

Here we are using children as the render prop. Inside the <ScrollPosition> component we will send a function which receives the position as a parameter.

在这里,我们将children用作渲染道具。 内的<ScrollPositi上>组件,我们将其发送接收功能s the po sition作为参数。

Render props can be used in situations where you need some reusable logic inside the component and you don’t want to wrap your component in a HOC.

在需要在组件内部使用一些可重用逻辑并且不想将组件包装在HOC中的情况下,可以使用渲染道具。

React-Motion is one of the libraries that offer some great examples of using render props.

React-Motion是提供使用渲染道具的一些出色示例的库之一。

Finally, let’s look at how we can integrate async flows with render props. Here’s a nice example of creating a reusable Fetch component.

最后,让我们看一下如何将异步流与渲染道具集成在一起。 这是创建可重用的Fetch组件的一个很好的示例。

I’m sharing a sandbox link so you can play with it and see the results.

我正在共享一个沙箱链接,以便您可以使用它并查看结果。

You can have multiple render props for the same component. With this pattern, you have endless possibilities of composing and reusing functionality.

同一组件可以有多个渲染道具。 使用这种模式,您可以无限地组合和重用功能。

What patterns do you use? Which of them would fit in this article? Drop me a message bellow or write your thoughts on Twitter.

您使用什么模式? 本文中哪一个适合? 给我留言或在Twitter上写下您的想法。

If you found this article useful, help me share it with the community!

如果您发现本文有用,请帮助我与社区分享!

翻译自: https://www.freecodecamp.org/news/evolving-patterns-in-react-116140e5fe8f/

react 模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值