ホームページ  >  記事  >  ウェブフロントエンド  >  React アプリ開発のための 4 つの実践的なヒント

React アプリ開発のための 4 つの実践的なヒント

青灯夜游
青灯夜游転載
2019-11-26 18:08:034332ブラウズ

React アプリ開発のための 4 つの実践的なヒント

# [関連トピックの推奨事項: 面接の質問に対応する (2020)]

#背景

フックは発売以来非常に人気があり、React コードの記述方法が変わり、より簡潔なコードを記述するのに役立ちます。

今日の記事はフックに関するものではありません。フックに加えて、

簡潔で明確なコードを書くのに役立つ実践的なテクニックがたくさんあります。

今日は、いくつかのテクニックを整理しました。そのうちのいくつかは、私が会社のプロジェクトで

実践したものでもあります。今、それらを整理して皆さんと共有します。インスピレーションになれば幸いです。あなた ### ###。 #Text

1. 文字列を使用して React 要素を定義します

簡単な例:

// 我们可以通过把一个字符串'p' 赋值给一个变量, 就像:
import React from 'react'

const MyComponent = 'p'

function App() {
  return (
    
      <mycomponent>
        <h3>I am inside a {'</h3>
<p></p>'} element
      </mycomponent>
    >
  )
}
React は内部で React.createElement

を呼び出し、この文字列を使用してこの要素を生成します。

さらに、

component を明示的に定義して、レンダリングされるコンテンツを決定することもできます。例:

// 定义一个MyComponent
function MyComponent({ component: Component = 'p', name, age, email }) {
  
  return (
    <component>
      <h1>Hi {name} </h1>
      
        <h6>You are {age} years old</h6>
        <small>Your email is {email}</small>
      >
    </component>
  )
}
適用可能なメソッド:

function App() {
  return (
    
      <mycomponent>
    >
  )
}</mycomponent>
This method 、次のようなカスタム コンポーネントを渡すこともできます。
function Dashboard({ children }) {
  return (
    

      {children}     

  ) } function App() {   return (            <mycomponent>     >   ) }</mycomponent>
同様の

要素または

を処理するコンポーネントが見つかった場合は、このカスタム方法で抽象化し、コードを簡素化できます。

実際の例を挙げます:

たとえば、商品の梱包を要求する必要があります。商品は個別に梱包することも、バッチで梱包することもできます。カスタム コンポーネントは、一般的な製品向けに作成できます。ポイント:

import React from 'react'
import withTranslate from '@components/withTranslate'
import PackComponent from './PackComponent'
import usePack, { check } from './usePack'

let PackEditor = (props) => {
  const packRes = usePack(props)
  return (
    <packcomponent></packcomponent>
  )
}

PackEditor = withTranslate(PackEditor)
PackEditor.check = check

export default PackEditor
このように、さまざまな業務モジュールで柔軟に使用でき、非常に便利です。

2. エラー境界を定義する

JavaScript では、発生する可能性のある例外をキャッチするために try/catch を使用します。 catch

でエラーを処理します。例:

function getFromLocalStorage(key, value) {
  try {
    const data = window.localStorage.get(key)
    return JSON.parse(data)
  } catch (error) {
    console.error
  }
}
このようにすると、エラーが発生した場合でも、アプリケーションが白い画面でクラッシュすることはありません。 React も結局は Javascript であり、本質的な違いはありませんので、try/catch も同様に使用して問題ありません。

ただし、React の実装メカニズムにより、コンポーネント内で Javascript エラーが発生すると内部状態が破壊され、レンダリングでエラーが生成されます:

https://github.com/facebook/ react/issues/4026

上記の理由に基づいて、React チームは

Error Boundaries

:React アプリ開発のための 4 つの実践的なヒント

https://reactjs .org/docs /error-boundaries.html

エラー境界

は、実際には React コンポーネントであり、コンポーネントを使用して、キャプチャされたエラー情報を処理できます。

コンポーネント ツリーが折りたたまれた場合、カスタマイズした UI をフォールバックとして表示することもできます。

React が提供する公式の例を見てください: https://reactjs.org/docs/error-boundaries.html#introducing-error-boundaries

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props)
    this.state = { hasError: false }
  }
  
  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true }
  }
  
  componentDidCatch(error, errorInfo) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, errorInfo)
  }
  
  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>
    }
    return this.props.children
  }
}

使用法:

<errorboundary>
  <mywidget></mywidget>
</errorboundary>

Dan Abramov によるライブ デモ:

https://codepen.io/gaearon/pen/wqvxGa?editors=0010

3. 高-コンポーネントの順序

平易な言葉で言うと、いわゆる上位コンポーネントとは、コンポーネントを投入し、いくつかの属性または操作を追加してからそれを投入することです。 一般的に、 という共通点を持ついくつかの

コンポーネントを

上位コンポーネント

に抽象化し、それを別のモジュール ## で

再利用することができます。 たとえば、私たちのシステムには、多くの場所で使用される border を追加する必要があるタイプのボタンがあります。これを抽象化します: <pre class="brush:php;toolbar:false">import React from 'react' // Higher order component const withBorder = (Component, customStyle) =&gt; {   class WithBorder extends React.Component {     render() {       const style = {         border: this.props.customStyle ? this.props.customStyle.border : '3px solid teal'       }       return &lt;component&gt;&lt;/component&gt;     }   }      return WithBorder } function MyComponent({ style, ...rest }) {   return (     &lt;p&gt;         &lt;/p&gt;&lt;h2&gt;           This is my component and I am expecting some styles.         &lt;/h2&gt;     </pre>

  ) } export default withBorder(MyComponent, { border: '4px solid teal' }) は Border で装飾されています MyComponent コンポーネントにはボーダーを統一する機能があり、後から修正したい場合はこの 中間層

で統一できるのでとても便利です。 私のプロジェクトでは、いくつかの上位コンポーネントも使用しています。具体的な例を挙げると:

PackEditor = withTranslate(PackEditor)

私たちの PackEditor は拡張コンポーネントです。どのような機能が追加されていますか?

名前が表すように、

withTranslate

は翻訳機能を追加します。このコンポーネントがどのように実装されているかを説明します: <pre class="brush:php;toolbar:false">import React from 'react' import { Provider } from 'react-redux' import { injectIntl } from 'react-intl' import { store } from '@redux/store' import { Intl } from './Locale' const withTranslate = BaseComponent =&gt; (props) =&gt; {   // avoid create a new component on re-render   const IntlComponent = React.useMemo(() =&gt; injectIntl(     ({ intl, ...others }) =&gt; (       &lt;basecomponent&gt; { // 注入翻译方法           if (!id) { return '' }           return intl.formatMessage(             typeof id === 'string' ? { id } : id,             values           )         }}         {...others}       /&gt;     )   ), [])   IntlComponent.displayName = `withTranslate(${BaseComponent.displayName || 'BaseComponent'})`      return (     &lt;provider&gt;       &lt;intl&gt;         &lt;intlcomponent&gt;&lt;/intlcomponent&gt;       &lt;/intl&gt;     &lt;/provider&gt;   ) } export default withTranslate&lt;/basecomponent&gt;</pre> 使用方法は非常に柔軟です:

rreeee

とても便利です。

4. Render props

Render prop は、React コンポーネント間の値を使用する関数を指します prop # の単純な技術##コードの共有はHOCに似ており、コンポーネント間のロジックの再利用の問題です。

より具体的には、Render プロパティは、どのコンテンツ をレンダリングする必要があるかをコンポーネントに伝える関数です。 簡単な例を見てみましょう: 次のコンポーネントは、Web アプリケーションでのマウスの位置を追跡します:

const Editor = withTranslate(({
  // ...
  translate,
}) => {
  // ...
   return (
     
      {translate('xxx')}}
     >
   )
})

カーソルが画面上を移動すると、コンポーネントはその (x ,y) 座標を表示します。 ここでの質問は次のとおりです:

この動作を別のコンポーネントで再利用するにはどうすればよいでしょうか?

换个说法,若另一个组件需要知道鼠标位置,我们能否封装这一行为,以便轻松地与其他组件共享它 ??

假设产品想要这样一个功能: 在屏幕上呈现一张在屏幕上追逐鼠标的猫的图片。

我们或许会使用

class Cat extends React.Component {
  render() {
    const mouse = this.props.mouse;
    return (
      <img  alt="React アプリ開発のための 4 つの実践的なヒント" >
    );
  }
}

这个需求如此简单,你可能就直接修改Mouse组件了:

class Mouse extends React.Component {
  state = { x: 0, y: 0 };

  handleMouseMove = (event) => {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <p>
        <cat></cat>
      </p>
    );
  }
}

巴适~ 简单粗暴, 一分钟完成任务。

可是,如果下次产品再要想加条狗呢

以上的例子,虽然可以完成了猫追鼠标的需求,还没有达到以可复用的方式真正封装行为的目标。

当我们想要鼠标位置用于不同的用例时,我们必须创建一个新的组件,专门为该用例呈现一些东西.

这也是 render prop 的来历:

我们可以提供一个带有函数 prop 的 <mouse></mouse> 组件,它能够动态决定什么需要渲染的,而不是将 硬编码 组件里.

修改一下上面的代码:

class Cat extends React.Component {
  render() {
    const mouse = this.props.mouse;
    return (
      <img  alt="React アプリ開発のための 4 つの実践的なヒント" >
    );
  }
}

class Mouse extends React.Component {
  state = { x: 0, y: 0 };

  handleMouseMove = (event) => {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      

        {this.props.render(this.state)}       

    );   } } class MouseTracker extends React.Component {   render() {     return (       

        

移动鼠标!

         (                    )}/>       

    );   } }

提供了一个render 方法,让动态决定什么需要渲染。

事实上,render prop 是因为模式才被称为 render prop ,不一定要用名为 render 的 prop 来使用这种模式。

任何被用于告知组件需要渲染什么内容的函数 prop, 在技术上都可以被称为 "render prop".

另外,关于 render prop 一个有趣的事情是你可以使用带有 render prop 的常规组件来实现大多数高阶组件 (HOC)。

例如,如果你更喜欢使用 withMouse HOC 而不是 组件,你可以使用带有 render prop 的常规 轻松创建一个:

function withMouse(Component) {
  return class extends React.Component {
    render() {
      return (
        <mouse> (
          <component></component>
        )}/>
      );
    }
  }
}</mouse>

也是非常的简洁清晰。

有一点需要注意的是, 如果你在定义的render函数里创建函数, 使用 render prop 会抵消使用 React.PureComponent 带来的优势。

因为浅比较 props 的时候总会得到 false,并且在这种情况下每一个 render 对于 render prop 将会生成一个新的值

class Mouse extends React.PureComponent {
  // 与上面相同的代码......
}

class MouseTracker extends React.Component {
  render() {
    return (
      
        <mouse> ( // 这是不好的! 每个渲染的 `render` prop的值将会是不同的。
          <cat></cat>
        )}/>
      >
    );
  }
}</mouse>

在这样例子中,每次 渲染,它会生成一个新的函数作为 的 prop,因而在同时也抵消了继承自 React.PureComponent 的 组件的效果.

为了绕过这一问题,有时你可以定义一个 prop 作为实例方法,类似这样:

class MouseTracker extends React.Component {
  renderTheCat(mouse) {
    return <cat></cat>;
  }

  render() {
    return (
      <p>
        </p><h1>Move the mouse around!</h1>
        <mouse></mouse>
      
    );
  }
}

5.组件性能

性能优化是永恒的主题, 这里不一一细说, 提供积分资源供你参考:

总结

以上几点都是我们经常要使用的技巧, 简单实用, 分享给大家, 希望能给大家带来一些帮助或启发,谢谢。

推荐阅读:React在线手册

以上がReact アプリ開発のための 4 つの実践的なヒントの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。