最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

編寫簡潔React組件的小技巧

 更新時間:2021年04月08日 10:25:27   作者:KooFE前端團(tuán)隊  
這篇文章主要介紹了編寫簡潔React組件的小技巧,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下

本文源于翻譯文章 Simple tips for writing clean React components, 原文作者 Iskander Samatov

在這篇文章中,我們會回顧一些簡單的技巧,它們將幫助我們編寫更簡潔的 React 組件,并且更好地擴(kuò)展我們的項目。

避免使用擴(kuò)展操作符傳遞 props

首先,讓我們從一個應(yīng)該避免的反模式開始。除非有明確的理由這樣做,否則應(yīng)該避免在組件樹中使用擴(kuò)展操作符傳遞props,比如:{ ...props }。

通過這種方式傳遞 props 確實可以更快的編寫組件。但這也使得我們很難去定位代碼中的 bug。會使我們對編寫的組件失去信心,會使得我們重構(gòu)組件變得更加困難,而且可能會導(dǎo)致出現(xiàn)很難排查的 bug。

將函數(shù)參數(shù)封裝成一個對象

如果函數(shù)接收多個參數(shù),最好將它們封裝成一個對象。舉個例子:

export const sampleFunction = ({ param1, param2, param3 }) => {
  console.log({ param1, param2, param3 });
}

以這種方式編寫函數(shù)簽名有幾個顯著的優(yōu)點:

  1. 你不用再擔(dān)心參數(shù)傳遞的順序。我曾犯過幾次因函數(shù)傳參順序問題而產(chǎn)生了 bug 的錯誤。
  2. 對于配置了智能提示的編輯器(現(xiàn)在的大多數(shù)都有),可以很好地完成函數(shù)參數(shù)的自動填充。

對于事件處理函數(shù),將該處理函數(shù)作為函數(shù)的返回值

如果你熟悉函數(shù)式編程,這種編程技術(shù)類似于函數(shù)柯里化,因為已經(jīng)提前設(shè)置了一些參數(shù)。

我們來看看這個例子:

import React from 'react'

export default function SampleComponent({ onValueChange }) {

  const handleChange = (key) => {
    return (e) => onValueChange(key, e.target.value)
  }

  return (
    <form>
      <input onChange={handleChange('name')} />
      <input onChange={handleChange('email')} />
      <input onChange={handleChange('phone')} />
    </form>
  )
}

如您所見,以這種方式編寫處理程序函數(shù),可以使組件樹保持簡潔。

組件渲染使用 map 而非 if/else

當(dāng)你需要基于自定義邏輯呈現(xiàn)不同的元素時,我建議使用使用 map 而非 if/else 語句。

下面是一個使用if/else的示例:

import React from 'react'

const Student = ({ name }) => <p>Student name: {name}</p>
const Teacher = ({ name }) => <p>Teacher name: {name}</p>
const Guardian = ({ name }) => <p>Guardian name: {name}</p>

export default function SampleComponent({ user }) {
  let Component = Student;
  if (user.type === 'teacher') {
    Component = Teacher
  } else if (user.type === 'guardian') {
    Component = Guardian
  }

  return (
    <div>
      <Component name={user.name} />
    </div>
  )
}

下面是一個使用map的示例:

import React from 'react'

const Student = ({ name }) => <p>Student name: {name}</p>
const Teacher = ({ name }) => <p>Teacher name: {name}</p>
const Guardian = ({ name }) => <p>Guardian name: {name}</p>

const COMPONENT_MAP = {
  student: Student,
  teacher: Teacher,
  guardian: Guardian
}

export default function SampleComponent({ user }) {
  const Component = COMPONENT_MAP[user.type]

  return (
    <div>
      <Component name={user.name} />
    </div>
  )
}

使用這個簡單的小策略,可以使你的組件變得更具有可讀性,更容易理解。而且它還使邏輯擴(kuò)展變得更簡單。

Hook組件

只要不濫用,這個模式是很有用的。

你可能會發(fā)現(xiàn)自己在應(yīng)用中使用了很多組件。如果它們需要一個狀態(tài)來發(fā)揮作用,你可以將他們封裝為一個 hook 提供該狀態(tài)。這些組件的一些好例子是彈出框、toast 通知或簡單的 modal 對話框。例如,下面是一個用于簡單確認(rèn)對話框的 hook 組件:

import React, { useCallback, useState } from 'react';
import ConfirmationDialog from 'components/global/ConfirmationDialog';

export default function useConfirmationDialog({
  headerText,
  bodyText,
  confirmationButtonText,
  onConfirmClick,
}) {
  const [isOpen, setIsOpen] = useState(false);

  const onOpen = () => {
    setIsOpen(true);
  };

  const Dialog = useCallback(
    () => (
      <ConfirmationDialog
        headerText={headerText}
        bodyText={bodyText}
        isOpen={isOpen}
        onConfirmClick={onConfirmClick}
        onCancelClick={() => setIsOpen(false)}
        confirmationButtonText={confirmationButtonText}
      />
    ),
    [isOpen]
  );

  return {
    Dialog,
    onOpen,
  };
}

你可以像這樣使用 hook 組件:

import React from "react";
import { useConfirmationDialog } from './useConfirmationDialog'

function Client() {
  const { Dialog, onOpen } = useConfirmationDialog({
    headerText: "Delete this record?",
    bodyText:
      "Are you sure you want delete this record? This cannot be undone.",
    confirmationButtonText: "Delete",
    onConfirmClick: handleDeleteConfirm,
  });

  function handleDeleteConfirm() {
    //TODO: delete
  }

  const handleDeleteClick = () => {
    onOpen();
  };

  return (
    <div>
      <Dialog />
      <button onClick={handleDeleteClick} />
    </div>
  );
}

export default Client;

以這種方式提取組件可以避免編寫大量狀態(tài)管理的樣板代碼。如果你想了解更多 React hooks,請查看 我的帖子。

組件拆分

下面三個技巧是關(guān)于如何巧妙地拆分組件。根據(jù)我的經(jīng)驗,保持組件的簡潔是保持項目可管理的最佳方法。

使用包裝器

如果你正在努力尋找一種方法來拆分復(fù)雜組件,看看你的組件中每個元素所提供的功能。有些元素提供了獨特的功能,比如拖拽功能。

下面是一個使用react-beautiful-dnd實現(xiàn)拖拽的組件示例:

import React from 'react'
import { DragDropContext, Droppable } from 'react-beautiful-dnd';
export default function DraggableSample() {
  function handleDragStart(result) { 
    console.log({ result });
  }
  function handleDragUpdate({ destination }) { 
    console.log({ destination });
  }
  const handleDragEnd = ({ source, destination }) => { 
    console.log({ source, destination });
  };
  return (
    <div>
      <DragDropContext
        onDragEnd={handleDragEnd}
        onDragStart={handleDragStart}
        onDragUpdate={handleDragUpdate}
      >
        <Droppable 
          droppableId="droppable"
          direction="horizontal"
        >
          {(provided) => (
            <div {...provided.droppableProps} ref={provided.innerRef}> 
              {columns.map((column, index) => {
                return (
                  <ColumnComponent
                    key={index}
                    column={column}
                  />
                );
              })}
            </div>
          )}
        </Droppable>
      </DragDropContext>
    </div>
  )
}

現(xiàn)在,看一下在我們將所有拖拽邏輯移到包裝器之后的組件:

import React from 'react'
export default function DraggableSample() {
  return (
    <div>
      <DragWrapper> 
      {columns.map((column, index) => { 
        return (
          <ColumnComponent key={index} column={column}/>
        );
      })}
      </DragWrapper>
    </div>
  )
}

下面是包裝器的代碼:

import React from 'react'
import { DragDropContext, Droppable } from 'react-beautiful-dnd';
export default function DragWrapper({children}) {
  function handleDragStart(result) { 
    console.log({ result });
  }
  function handleDragUpdate({ destination }) { 
    console.log({ destination });
  }
  const handleDragEnd = ({ source, destination }) => { 
    console.log({ source, destination });
  };
  return (
    <DragDropContext 
      onDragEnd={handleDragEnd}
      onDragStart={handleDragStart} 
      onDragUpdate={handleDragUpdate}
    >
      <Droppable droppableId="droppable" direction="horizontal"> 
        {(provided) => (
          <div {...provided.droppableProps}  ref={provided.innerRef}> 
            {children}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  )
}

因此,可以更直觀地看到組件在更高層次上的功能。所有用于拖拽的功能都在包裝器中,使得代碼更容易理解。

關(guān)注點分離

這是我最喜歡的拆分較大組件的方法。

從 React 角度出發(fā),關(guān)注點的分離意味著分離組件中負(fù)責(zé)獲取和改變數(shù)據(jù)的部分和純粹負(fù)責(zé)顯示元素的部分。

這種分離關(guān)注點的方法是引入 hooks 的主要原因。你可以用自定義 hook 封裝所有方法或全局狀態(tài)連接的邏輯。

例如,讓我們看看如下組件:

import React from 'react'
import { someAPICall } from './API' 
import ItemDisplay from './ItemDisplay'
export default function SampleComponent() { 
  const [data, setData] = useState([])
  useEffect(() => { 
    someAPICall().then((result) => { setData(result)})
  }, [])
  function handleDelete() { console.log('Delete!'); }
  function handleAdd() { console.log('Add!'); }
  const handleEdit = () => { console.log('Edit!'); };
  return (
    <div>
      <div>
        {data.map(item => <ItemDisplay item={item} />)} 
      </div>
      <div>
        <button onClick={handleDelete} /> 
        <button onClick={handleAdd} /> 
        <button onClick={handleEdit} /> 
      </div>
    </div>
  )
}

下面是它的重構(gòu)版本,使用自定義hook拆分后的代碼:

import React from 'react'
import ItemDisplay from './ItemDisplay'
export default function SampleComponent() {
  const { data, handleDelete, handleEdit, handleAdd } = useCustomHook()
  return (
    <div>
      <div>
        {data.map(item => <ItemDisplay item={item} />)} 
      </div>
      <div>
        <button onClick={handleDelete} /> 
        <button onClick={handleAdd} /> 
        <button onClick={handleEdit} /> 
      </div>
    </div>
  )
}

這是該 hook 本身的代碼:

import { someAPICall } from './API'
export const useCustomHook = () => { 
  const [data, setData] = useState([])
  useEffect(() => { 
    someAPICall().then((result) => { setData(result)})
  }, [])
  function handleDelete() { console.log('Delete!'); }
  function handleAdd() { console.log('Add!'); }
  const handleEdit = () => { console.log('Edit!'); };
  return { handleEdit, handleAdd, handleDelete, data }
}

每個組件封裝為一個單獨的文件

通常大家會這樣寫代碼:

import React from 'react'
export default function SampleComponent({ data }) {
  const ItemDisplay = ({ name, date }) => ( 
    <div>
      <h3>{name}</h3>
      <p>{date}</p>
    </div> 
  )
  return (
    <div>
      <div>
        {data.map(item => <ItemDisplay item={item} />)}
      </div>
    </div> 
  )
}

雖然用這種方式編寫 React 組件沒有什么大問題,但這并不是一個好的做法。將 ItemDisplay 組件移動到一個單獨的文件可以使你的組件松散耦合,易于擴(kuò)展。

在大多數(shù)情況下,要編寫干凈整潔的代碼,需要注意并花時間遵循好的模式和避免反模式。因此,如果你花時間遵循這些模式,它有助于你編寫整潔的 React 組件。我發(fā)現(xiàn)這些模式在我的項目中非常有用,希望你也這么做!

以上就是編寫簡潔React組件的小技巧的詳細(xì)內(nèi)容,更多關(guān)于編寫React組件的技巧的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺談React底層實現(xiàn)原理

    淺談React底層實現(xiàn)原理

    本文主要介紹了淺談React底層實現(xiàn)原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • react hook使用useState更新數(shù)組,無法更新問題及解決

    react hook使用useState更新數(shù)組,無法更新問題及解決

    這篇文章主要介紹了react hook使用useState更新數(shù)組,無法更新問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 從零開始最小實現(xiàn)react服務(wù)器渲染詳解

    從零開始最小實現(xiàn)react服務(wù)器渲染詳解

    這篇文章主要介紹了從零開始最小實現(xiàn)react服務(wù)器渲染詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • 使用React?MUI庫實現(xiàn)用戶列表分頁功能

    使用React?MUI庫實現(xiàn)用戶列表分頁功能

    MUI是一款基于React的UI組件庫,可以方便地構(gòu)建美觀的用戶界面,使用MUI的DataTable組件和分頁器組件可以輕松實現(xiàn)用戶列表分頁功能,這篇文章使用MUI庫實現(xiàn)了用戶列表分頁功能,感興趣的同學(xué)可以參考下文
    2023-05-05
  • 五分鐘教你了解一下react路由知識

    五分鐘教你了解一下react路由知識

    本文主要介紹了react路由知識,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • React使用fullpage.js實現(xiàn)整屏翻頁功能

    React使用fullpage.js實現(xiàn)整屏翻頁功能

    最近筆者在完成一個移動端小項目的過程中需要實現(xiàn)整屏翻頁的效果;調(diào)研完畢之后,最終決定使用pullPage.js實現(xiàn)此功能,fullPage.js使用起來比較方便,并且官網(wǎng)上也給了在react項目中使用的demo,本文記錄了這個第三方庫的使用過程,感興趣的朋友可以參考下
    2023-11-11
  • 基于visual studio code + react 開發(fā)環(huán)境搭建過程

    基于visual studio code + react 開發(fā)環(huán)境搭建過程

    今天通過本文給大家分享基于visual studio code + react 開發(fā)環(huán)境搭建過程,本文給大家介紹的非常詳細(xì),包括react安裝問題及安裝 Debugger for Chrome的方法,需要的朋友跟隨小編一起看看吧
    2021-07-07
  • react ant design樣式覆蓋問題

    react ant design樣式覆蓋問題

    這篇文章主要介紹了react ant design樣式覆蓋問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • react配置px轉(zhuǎn)換rem的方法

    react配置px轉(zhuǎn)換rem的方法

    這篇文章主要介紹了react配置px轉(zhuǎn)換rem的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • React修改數(shù)組對象的注意事項及說明

    React修改數(shù)組對象的注意事項及說明

    這篇文章主要介紹了React修改數(shù)組對象的注意事項及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評論

温宿县| 江山市| 镇巴县| 永修县| 安康市| 松原市| 琼海市| 宜兰县| 屯昌县| 渝中区| 泊头市| 石阡县| 平顺县| 康乐县| 息烽县| 清水县| 高台县| 城口县| 宣化县| 三原县| 施甸县| 盘山县| 田东县| 高淳县| 马关县| 花莲市| 莒南县| 南康市| 庄浪县| 始兴县| 铁力市| 黄石市| 易门县| 高淳县| 资溪县| 鄱阳县| 富裕县| 云霄县| 青岛市| 无极县| 涪陵区|