目錄
I am inside a {'
Hi {name} 
You are {age} years old
Something went wrong.
移动鼠标!
Move the mouse around!
首頁 web前端 js教程 4個開發React應用的實用技巧

4個開發React應用的實用技巧

Nov 26, 2019 pm 06:08 PM
javascript node.js react.js typescript vue.js

4個開發React應用的實用技巧

【相關專題推薦:react面試題(2020)】

背景

Hooks 自推出以來就很火, 它改變了我們編寫React 程式碼的方式, 有助於我們寫更簡潔的程式碼。

今天這邊文章不是說Hooks的,Hooks之外, 還有很多實用的技巧可以幫助我們寫出簡潔清晰的程式碼。

今天我就整理了幾個使用的技巧,其中有些也是我在公司專案中實踐的,現在整理出來分享給大家, 希望對大家有所啟發

正文

#1. 使用字串來定義一個React元素

#舉個簡單的例子:

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

const MyComponent = 'p'

function App() {
  return (
    
      <mycomponent>
        <h3 id="I-am-inside-a">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 id="Hi-name">Hi {name} </h1>
      
        <h6 id="You-are-age-years-old">You are {age} years old</h6>
        <small>Your email is {email}</small>
      >
    </component>
  )
}
登入後複製

適用方式:

function App() {
  return (
    
      <mycomponent>
    >
  )
}</mycomponent>
登入後複製

這種方式, 你也可以傳入一個自訂的元件, 例如:

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 錯誤會破壞內部狀態, render會產生錯誤:

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

4個開發React應用的實用技巧

基於以上原因,React 團隊引入了Error Boundaries:

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

Error boundaries, 其實就是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 id="Something-went-wrong">Something went wrong.</h1>
    }
    return this.props.children
  }
}
登入後複製

使用方式:

<errorboundary>
  <mywidget></mywidget>
</errorboundary>
登入後複製

Live Demo By Dan Abramov:

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

3.高階元件

通俗點講, 所謂高階元件就是, 你丟一個元件進去, 增加一些屬性或操作, 再丟出來。

一般來說, 你可以把一些具備共同點的元件抽象化成一個高階元件, 然後再不同的模組中重複使用

例如, 我們的系統中, 有一類按鈕要加個border, 很多地方都要用到, 我們把它抽像出來:

import React from 'react'

// Higher order component
const withBorder = (Component, customStyle) => {
  class WithBorder extends React.Component {
    render() {
      const style = {
        border: this.props.customStyle ? this.props.customStyle.border : '3px solid teal'
      }
      return <component></component>
    }
  }
  
  return WithBorder
}

function MyComponent({ style, ...rest }) {
  return (
    <p>
        </p><h2>
          This is my component and I am expecting some styles.
        </h2>
    
  )
}

export default withBorder(MyComponent, { border: '4px solid teal' })
登入後複製

經過withBorder裝飾的MyComponent元件, 就具備了統一border這項功能, 後面如果如果要做修改, 就可以在這個中間層統一處理, 非常方便。

在我的專案裡, 也用了一些高階元件, 舉個具體的例子:

PackEditor = withTranslate(PackEditor)
登入後複製

我們的這個PackEditor 就是一個增強過的元件,增加了什麼功能呢?

如同名字表達的, withTranslate, 增加了一個翻譯功能, 下面也給大家看看這個元件是怎麼實現的:

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 => (props) => {
  // avoid create a new component on re-render
  const IntlComponent = React.useMemo(() => injectIntl(
    ({ intl, ...others }) => (
      <basecomponent> { // 注入翻译方法
          if (!id) { return '' }
          return intl.formatMessage(
            typeof id === 'string' ? { id } : id,
            values
          )
        }}
        {...others}
      />
    )
  ), [])

  IntlComponent.displayName = `withTranslate(${BaseComponent.displayName || 'BaseComponent'})`
  
  return (
    <provider>
      <intl>
        <intlcomponent></intlcomponent>
      </intl>
    </provider>
  )
}

export default withTranslate</basecomponent>
登入後複製

用法很靈過:

const Editor = withTranslate(({
  // ...
  translate,
}) => {
  // ...
   return (
     
      {translate('xxx')}}
     >
   )
})
登入後複製

十分的方便。

4. Render props

Rrender prop 是指一種在React 元件之間使用一個值為函數的prop 共享代碼的簡單技術, 和HOC 類似,都是組件間的邏輯復用問題

更具體地說,Render prop 是一個用來告知元件需要渲染什麼內容的函數。

下面看一下簡單的例子:

以下元件追蹤Web 應用程式中的滑鼠位置:

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

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

  render() {
    return (
      <p>
        </p><p>The current mouse position is ({this.state.x}, {this.state.y})</p>
      
    );
  }
}

class MouseTracker extends React.Component {
  render() {
    return (
      
        <h1 id="移动鼠标">移动鼠标!</h1>
        <mouse></mouse>
      >
    );
  }
}
登入後複製

當遊標在螢幕上移動時,元件顯示其(x ,y)座標。

現在的問題是:

我們如何在另一個元件中重複使用這個行為?

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

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

我们或许会使用

class Cat extends React.Component {
  render() {
    const mouse = this.props.mouse;
    return (
      <img  src="/static/imghw/default1.png" data-src="/cat.jpg" class="lazy" alt="4個開發React應用的實用技巧" >
    );
  }
}
登入後複製

这个需求如此简单,你可能就直接修改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  src="/static/imghw/default1.png" data-src="/cat.jpg" class="lazy" alt="4個開發React應用的實用技巧" >
    );
  }
}

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 id="Move-the-mouse-around">Move the mouse around!</h1>
        <mouse></mouse>
      
    );
  }
}
登入後複製

5.组件性能

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

总结

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

推荐阅读:React在线手册

以上是4個開發React應用的實用技巧的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

如何在JavaScript中取得HTTP狀態碼的簡單方法 如何在JavaScript中取得HTTP狀態碼的簡單方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務

JS 的 AI 時代來了! JS 的 AI 時代來了! Apr 08, 2024 am 09:10 AM

JS-Torch簡介JS-Torch是一種深度學習JavaScript函式庫,其語法與PyTorch非常相似。它包含一個功能齊全的張量物件(可與追蹤梯度),深度學習層和函數,以及一個自動微分引擎。 JS-Torch適用於在JavaScript中進行深度學習研究,並提供了許多方便的工具和函數來加速深度學習開發。圖片PyTorch是一個開源的深度學習框架,由Meta的研究團隊開發和維護。它提供了豐富的工具和函式庫,用於建立和訓練神經網路模型。 PyTorch的設計理念是簡單和靈活,易於使用,它的動態計算圖特性使

Golang 和 Node.js 在後端開發的對比 Golang 和 Node.js 在後端開發的對比 Jun 03, 2024 pm 02:31 PM

Go和Node.js在類型化(強/弱)、並發(goroutine/事件循環)、垃圾收集(自動/手動)上有差異。 Go具備高吞吐量、低延遲,適用於高負載後端;Node.js擅長異步I/O,適合高並發、短請求。兩者的實戰案例包括Kubernetes(Go)、資料庫連線(Node.js)、網路應用程式(Go/Node.js)。最終選擇取決於應用程式需求、團隊技能和個人偏好。

JavaScript和WebSocket:打造高效率的即時搜尋引擎 JavaScript和WebSocket:打造高效率的即時搜尋引擎 Dec 17, 2023 pm 10:13 PM

JavaScript和WebSocket:打造高效率的即時搜尋引擎引言:隨著網路的發展,使用者對即時搜尋引擎的要求也越來越高。傳統的搜尋引擎在進行搜尋時,使用者需要點擊搜尋按鈕後才能得到結果,這種方式無法滿足使用者對於即時搜尋結果的需求。因此,採用JavaScript和WebSocket技術來實現即時搜尋引擎成為了一個熱門的話題。本文將詳細介紹使用JavaScri

VUE是用於前端還是後端? VUE是用於前端還是後端? Apr 03, 2025 am 12:07 AM

Vue.js主要用於前端開發。 1)它是一個輕量級且靈活的JavaScript框架,專注於構建用戶界面和單頁面應用。 2)Vue.js的核心是其響應式數據系統,數據變化時視圖自動更新。 3)它支持組件化開發,UI可拆分為獨立、可複用的組件。

See all articles