5個技巧助你編寫更好的React程式碼
在本文中,我想分享幾個技巧,這些技巧將改善你的react程式碼。
1. 解構props
在js中解構物件(尤其是props)可以大大減少程式碼中的重複。看下面的例子:
//Parent Component
import react from 'react';
import CoffeeCard from './CoffeeCard';
const CafeMenu = () => {
const coffeeList = [
{
id: '0',
name: 'Espresso',
price: '2.00',
size: '16'
},
{
id: '1',
name: 'Cappuccino',
price: '3.50',
size: '24'
},
{
id: '2',
name: 'Caffee Latte',
price: '2.70',
size: '12'
}
];
return coffeeList.map(item => (
<CoffeeCard key={item.id} coffee={item} />
));
};
export default CafeMenu;
CafeMenu元件用於儲存可用飲料的列表,現在我們想要建立另一個可以顯示一種飲料的元件。如果不對props進行解構,我們的程式碼將像下面這樣:
//Child Component
import React from 'react';
const CoffeeCard = props => {
return (
<div>
<h1>{props.coffee.name}</h1>
<p>Price: {props.coffee.price}$</p>
<p>Size: {props.coffee.size} oz</p>
</div >
);
};
export default CoffeeCard;
如你所見,它看起來並不好,每次我們需要獲取某個屬性時,都要重複props.coffee,幸運的是,我們可以通過解構來簡化它。
//Child Component (after destructuring props)
import React from 'react';
const CoffeeCard = props => {
const { name, price, size } = props.coffee;
return (
<div>
<h1>{name}</h1>
<p>Price: {price}$</p>
<p>Size: {size} oz</p>
</div>
);
};
export default CoffeeCard;
如果我們想將大量引數傳遞給子元件,我們還可以直接在建構函式(或函式元件的引數)中解構props。比如:
//Parent Component
import React from 'react';
import ContactInfo from './ContactInfo';
const UserProfile = () => {
const name = 'John Locke';
const email = '[email protected]';
const phone = '01632 960668';
return <ContactInfo name={name} email={email} phone={phone} />;
};
export default UserProfile;
//Child Component
import React from 'react';
const ContactInfo = ({ name, email, phone }) => {
return (
<div>
<h1>{name}</h1>
<p> E-mail: {email}</p>
<p> Phone: {phone}</p>
</div>
);
};
export default ContactInfo;
2. 保持匯入模組的順序
有時(尤其是在“容器元件”中),我們需要使用許多不同的模組,並且元件匯入看上去有些混亂,如:
import { Auth } from 'aws-amplify';
import React from 'react';
import SidebarNavigation from './components/SidebarNavigation';
import { EuiPage, EuiPageBody } from '@elastic/eui';
import { keyCodes } from '@elastic/eui/lib/services';
import './index.css'
import HeaderNavigation from './components/HeaderNavigation';
import Routes from './Routes';
關於匯入模組的理想順序有很多不同的觀點。我建議多參考,然後找到適合你自己的那種。
至於我自己,我通常按型別對匯入進行分組,並按字母順序對它們進行排序(這是可選操作)。我也傾向於保持以下順序:
- 標準模組
- 第三方模組
- 自己程式碼匯入(元件)
- 特定於模組的匯入(例如css,PNG等)
- 僅用於測試的程式碼
快速重構一下,我們的模組匯入看上去舒服多了了。
import React from 'react';
import { Auth } from 'aws-amplify';
import { EuiPage, EuiPageBody } from '@elastic/eui';
import { keyCodes } from '@elastic/eui/lib/services';
import HeaderNavigation from './components/HeaderNavigation';
import SidebarNavigation from './components/SidebarNavigation';
import Routes from './Routes';
import './index.css'
3.使用Fragments
在我們的元件中,我們經常返回多個元素。一個React元件不能返回多個子節點,因此我們通常將它們包裝在div中。有時,這樣的解決方案會有問題。比如下面的這個例子中:
我們要建立一個Table元件,其中包含一個Columns元件。
import React from 'react';
import Columns from './Columns';
const Table = () => {
return (
<table>
<tbody>
<tr>
<Columns />
</tr>
</tbody>
</table>
);
};
export default Table;
Columns元件中包含一些td元素。由於我們無法返回多個子節點,因此需要將這些元素包裝在div中。
import React from 'react';
const Columns = () => {
return (
<div>
<td>Hello</td>
<td>World</td>
</div>
);
};
export default Columns;
然後就報錯了,因為tr標籤中不能放置div。我們可以使用Fragment標籤來解決這個問題,如下所示:
import React, { Fragment } from 'react';
const Columns = () => {
return (
<Fragment>
<td>Hello</td>
<td>World</td>
</Fragment>
);
};
export default Columns;
我們可以將Fragment視為不可見的div。它在子元件將元素包裝在標籤中,將其帶到父元件並消失。
你也可以使用較短的語法,但是它不支援key和屬性。
import React from 'react';
const Columns = () => {
return (
<>
<td>Hello</td>
<td>World</td>
</>
);
};
export default Columns;
4. 使用展示元件和容器元件
將應用程式的元件分為展示(木偶)元件和容器(智慧)元件。如果你不知道這些是什麼,可以下面的介紹:
展示元件
- 主要關注UI,它們負責元件的外觀。
- 資料由props提供,木偶元件中不應該呼叫API,這是智慧元件的工作
- 除了UI的依賴包,它們不需要依賴應用程式
- 它們可能包括狀態,但僅用於操縱UI本身-它們不應儲存應用程式資料。
木偶元件有:載入指示器,模態,按鈕,輸入。
容器元件
- 它們不關注樣式,通常不包含任何樣式
- 它們用於處理資料,可以請求資料,捕獲更改和傳遞應用程式資料
- 負責管理狀態,重新渲染元件等等
- 可能依賴於應用程式,呼叫Redux,生命週期方法,API和庫等等。
使用展示元件和容器元件的好處
- 更好的可讀性
- 更好的可重用性
- 更容易測試
此外,它還符合“單一責任原則” - 一個元件負責外觀,另一個元件負責資料。
示例
讓我們看一個簡單的例子。這是一個BookList元件,該元件可從API獲取圖書資料並將其顯示在列表中。
import React, { useState, useEffect } from 'react';
const BookList = () => {
const [books, setBooks] = useState([]);
const [isLoading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
fetch('api/books')
.then(res => res.json())
.then(books => {
setBooks(books);
setLoading(false);
});
}, []);
const renderLoading = () => {
return <p>Loading...</p>;
};
const renderBooks = () => {
return (
<ul>
{books.map(book => (
<li>{book.name}</li>
))}
</ul>
);
};
return <>{isLoading ? renderLoading() : renderBooks()}</>;
};
export default BookList;
該元件的問題在於,它負責太多事情。它獲取並呈現資料。它還與一個特定的介面關聯,因此在不復制程式碼的情況下,不能使用此元件顯示特定使用者的圖書列表。
現在,讓我們嘗試將此元件分為展示元件和容器元件。
import React from 'react';
const BookList = ({ books, isLoading }) => {
const renderLoading = () => {
return <p>Loading...</p>;
};
const renderBooks = () => {
return (
<ul>
{books.map(book => (
<li key={book.id}>{book.name}</li>
))}
</ul>
);
};
return <>{isLoading ? renderLoading() : renderBooks()}</>;
};
export default BookList;
import React, { useState, useEffect } from 'react';
import BookList from './BookList';
const BookListContainer = () => {
const [books, setBooks] = useState([]);
const [isLoading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
fetch('/api/books')
.then(res => res.json())
.then(books => {
setBooks(books);
setLoading(false);
});
}, []);
return <BookList books={books} isLoading={isLoading} />;
};
export default BookListContainer;
如你所見,它看起來要好得多。更重要的是,它使我們可以在具有不同資料的許多地方使用BookList元件。
豌豆資源搜尋網站https://55wd.com 電腦刺繡繡花廠 ttp://www.szhdn.com
5. 使用styled-components
對React元件進行樣式設定一直是個難題。查詢拼寫錯誤的類名,維護大型CSS檔案,處理相容性問題有時可能很痛苦。
styled-components是一個常見的css in js類庫,和所有同類型的類庫一樣,通過js賦能解決了原生css所不具備的能力,比如變數、迴圈、函式等。
要開始使用styled-components,你需要首先安裝依賴:
npm i styled-components
下面是一個示例:
import React from 'react';
import styled from 'styled-components';
const Grid = styled.div`
display: flex;
`;
const Col = styled.div`
display: flex;
flex-direction: column;
`;
const MySCButton = styled.button`
background: ${props => (props.primary ? props.mainColor : 'white')};
color: ${props => (props.primary ? 'white' : props.mainColor)};
display: block;
font-size: 1em;
margin: 1em;
padding: 0.5em 1em;
border: 2px solid ${props => props.mainColor};
border-radius: 15px;
`;
function App() {
return (
<Grid>
<Col>
<MySCButton mainColor='#ee6352' primary>My 1st Button</MySCButton>
<MySCButton mainColor='#ee6352'>My 2st Button</MySCButton>
<MySCButton mainColor='#ee6352'>My 3st Button</MySCButton>
</Col>
<Col>
<MySCButton mainColor='#515052' primary>My 4st Button</MySCButton>
<MySCButton mainColor='#515052'>My 5st Button</MySCButton>
<MySCButton mainColor='#515052'>My 6st Button</MySCButton>
</Col>
</Grid>
);
}
export default App;
這只是樣式化元件如何工作的一個簡單示例,但是它們可以做的還遠遠不止這些。你可以在其官方文件中瞭解有關樣式化元件的更多資訊。