欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

編寫簡潔React組件的小技巧

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

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

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

避免使用擴展操作符傳遞 props

首先,讓我們從一個應(yīng)該避免的反模式開始。除非有明確的理由這樣做,否則應(yīng)該避免在組件樹中使用擴展操作符傳遞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

當你需要基于自定義邏輯呈現(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>
  )
}

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

Hook組件

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

你可能會發(fā)現(xiàn)自己在應(yīng)用中使用了很多組件。如果它們需要一個狀態(tài)來發(fā)揮作用,你可以將他們封裝為一個 hook 提供該狀態(tài)。這些組件的一些好例子是彈出框、toast 通知或簡單的 modal 對話框。例如,下面是一個用于簡單確認對話框的 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)注點的分離意味著分離組件中負責(zé)獲取和改變數(shù)據(jù)的部分和純粹負責(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 組件移動到一個單獨的文件可以使你的組件松散耦合,易于擴展。

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

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

相關(guān)文章

  • react底層的四大核心內(nèi)容架構(gòu)詳解

    react底層的四大核心內(nèi)容架構(gòu)詳解

    這篇文章主要為大家詳細介紹了react四大核心內(nèi)容架構(gòu),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • React?中使用?Redux?的?4?種寫法小結(jié)

    React?中使用?Redux?的?4?種寫法小結(jié)

    這篇文章主要介紹了在?React?中使用?Redux?的?4?種寫法,Redux 一般來說并不是必須的,只有在項目比較復(fù)雜的時候,比如多個分散在不同地方的組件使用同一個狀態(tài),本文就React使用?Redux的相關(guān)知識給大家介紹的非常詳細,需要的朋友參考下吧
    2022-06-06
  • react中實現(xiàn)搜索結(jié)果中關(guān)鍵詞高亮顯示

    react中實現(xiàn)搜索結(jié)果中關(guān)鍵詞高亮顯示

    這篇文章主要介紹了react中實現(xiàn)搜索結(jié)果中關(guān)鍵詞高亮顯示,使用react實現(xiàn)要比js簡單很多,方法都是大同小異,具體實現(xiàn)代碼大家跟隨腳本之家小編一起看看吧
    2018-07-07
  • React通過hook實現(xiàn)封裝表格常用功能

    React通過hook實現(xiàn)封裝表格常用功能

    這篇文章主要為大家詳細介紹了React通過hook封裝表格常用功能的使用,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考下
    2023-12-12
  • react-native fetch的具體使用方法

    react-native fetch的具體使用方法

    本篇文章主要介紹了react-native fetch的具體使用方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • React實現(xiàn)復(fù)雜搜索表單的展開收起功能

    React實現(xiàn)復(fù)雜搜索表單的展開收起功能

    本節(jié)對于需要展開收起效果的查詢表單進行概述,主要涉及前端樣式知識。對React實現(xiàn)復(fù)雜搜索表單的展開-收起功能感興趣的朋友一起看看吧
    2021-09-09
  • React項目中使用Redux的?react-redux

    React項目中使用Redux的?react-redux

    這篇文章主要介紹了React項目中使用Redux的?react-redux,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • React中g(shù)etDefaultProps的使用小結(jié)

    React中g(shù)etDefaultProps的使用小結(jié)

    React中的getDefaultProps功能允許開發(fā)者為類組件定義默認屬性,提高組件的靈活性和容錯性,本文介紹了getDefaultProps的作用、語法以及最佳實踐,并探討了其他替代方案,如函數(shù)組件中的默認參數(shù)、高階組件和ContextAPI等,理解這些概念有助于提升代碼的可維護性和用戶體驗
    2024-09-09
  • 詳解如何使用Jest測試React組件

    詳解如何使用Jest測試React組件

    在本文中,我們將了解如何使用Jest(Facebook 維護的一個測試框架)來測試我們的React組件,我們將首先了解如何在純 JavaScript 函數(shù)上使用 Jest,然后再了解它提供的一些開箱即用的功能,這些功能專門用于使測試 React 應(yīng)用程序變得更容易,需要的朋友可以參考下
    2023-10-10
  • React 封裝自定義組件的操作方法

    React 封裝自定義組件的操作方法

    React中自定義組件的重要性在于它們提供了代碼重用、降低耦合性、提升可維護性、更好的團隊協(xié)作、靈活性和易于測試和調(diào)試等好處,從而提高了開發(fā)效率和質(zhì)量,這篇文章主要介紹了React 封裝自定義組件,需要的朋友可以參考下
    2023-12-12

最新評論