如何减小 React 组件的大小:3 个专业技巧
如何减小 React 组件的大小:3 个专业技巧
在工作过程中,许多代码片段增长得如此之快,以至于很容易失去对它们的控制。我们正在谈论 React 组件。将具有许多功能、JSX 和配置的组件挤在一起成为那些开始学习 React 的人的主要问题之一。让我们看看如何避免它。
以其中一个 UI 组件为例 - 桌子
.让我们尝试优化它的音量,为此使用 3 个技巧。
零件 桌子
将有几个可以在未来扩展的功能。
- 获取标题和行作为参数并呈现表格。
- 获取排序器作为参数来确定要排序的标头。
- 切换表头会触发升序和降序排序。
该应用程序将如下所示:
从“反应”导入反应
从'./components/Table'导入表
函数应用程序(){
常量头 = {
名称:'名称',
起源:'起源',
largeCountry: '最大的出口国',
productionInBillions: '生产 (BLN)',
}
常量行 = [
{
名称:'苹果',
原产地:“西班牙”,
最大的国家:'印度',
productionInBillions: '1.5',
},
{
名称:'芒果',
原产地:'印度',
最大的国家:'印度',
productionInBillions: '1.9',
},
{
名称:'鳄梨',
原产地:'美国',
最大的国家:'美国',
productionInBillions: '1.9',
},
{
名称:“百香果”,
原产地:'美国',
最大的国家:'美国',
productionInBillions: '1.7',
},
]
常量排序 = {
名称:真实,
出处:真实,
productionInBillions: true,
}
返回<Table headers={headers} rows={rows} sorters={sorters} />
}
导出默认应用
最初,表格组件将如下所示。我们稍后会对其进行优化。
桌子 {
字体系列:arial、sans-serif;
边框折叠:折叠;
宽度:100%;
}
td,
第 {
边框:1px 实心#dddddd;
文本对齐:左;
填充:8px;
}
tr:nth-child(偶数) {
背景颜色:#dddddd;
}
.sort-icon {
显示:内联;
}
从“反应”导入反应,{ FunctionComponent,useEffect,useState }
导入'./Table.css'
接口 TableProps {
标题:记录<string, string>
排序?:记录<string, boolean>
行:记录<string, string>[]
}
常量表:函数组件<TableProps>= ({ 标题、行、排序器 }) => {
const isSortable = Boolean(sorters)
const [displayedRows, setDisplayedRows] = useState(rows)
const [sortersData, setSortersData] = useState(sorters)
const [currentSort, setCurrentSort] = useState('')
使用效果(()=> {
if (!isSortable || currentSort === '') {
返回
}
常量 sortedRows = rows.sort(
(一个记录<string, string>, b: 记录<string, string>) => {
if (sortersData![currentSort]) {
返回 a[currentSort] < b[currentSort] ? 1:-1
} else if (!sortersData![currentSort]) {
返回 a[currentSort] > b[currentSort] ? 1:-1
}
返回 0
},
)
setDisplayedRows([...sortedRows])
},[排序数据])
const handleSortToggled = (headerKey: string, isAsc: boolean) => {
如果(!isSortable){
返回
}
常量 newIsAsc = !isAsc
sortersData![headerKey] = newIsAsc
设置当前排序(标题键)
setSortersData({ ...sortersData })
}
返回 (
<>
<table>
<thead>
<tr>
{Object.keys(headers).map((headerKey: string, index: number) => (
<th key={'col' + index}>
{标头[标头键]}
{isSortable && sortersData![headerKey] !== 未定义 && (
<div
className="排序图标"
onClick={() =>
handleSortToggled(headerKey, sortersData![headerKey])
}
>
{sortersData![headerKey]? <>∧</> : <>∨</> }
</div>
)}
</th>
))}
</tr>
</thead>
<tbody>
{displayedRows.map((行:记录<string, string>, 索引: 数字) => (
<tr key={'row' + index}>
{Object.values(row).map((cell: string, cellIndex: number) => (
<td key={'cell' + cellIndex}>{细胞}</td>
))}
</tr>
))}
</tbody>
</table>
</>
)
}
导出默认表
命名空间功能
在 React 组件中,类型(接口、枚举)和常量的数量通常会增加。在第一种方法中,我们将使用命名空间。配置文件可以存储常量、类型,甚至是纯辅助函数,因此它们不需要留在组件中。让我们仔细看看:
导出命名空间表配置 {
导出类型行 = 记录<string, string>
导出类型 Header = 记录<string, string>
导出类型排序器 = 记录<string, boolean>
导出接口 TableProps {
标头:标头
行:行[]
排序?:排序
}
}
然后就可以更新组件的props(道具)类型了 桌子
:
...
从 './TableConfig' 导入 { TableConfig } 常量表:函数组件<TableConfig.TableProps>= ({
...
2.划分子组件和共享状态
至此,我们知道类型、常量和辅助函数可以移动到哪里。现在我们弄清楚如何处理子组件。这些是主要大组件被拆分成的小子组件。应考虑两个特点。
- 始终在主组件的主体之外创建子组件,无论是在同一个文件中还是在其他文件中。否则,会出现性能问题,并且每次更新状态时都会创建子组件。
- 利用
语境
如果您想共享主组件的状态以避免属性重载。
让我们看一个例子:
导入反应,{
创建上下文,
功能组件,
使用上下文,
使用效果,
使用状态,
} 从“反应”
导入'./Table.css'
从 './TableConfig' 导入 { TableConfig }
常量表上下文 = 创建上下文<Record<string, any> >({})
常量头:FunctionComponent<{ headerKey: string }> = ({ headerKey }) => {
const { headers, isSortable, sortersData, handleSortToggled } = useContext(
表上下文,
)
返回 (
<th>
{标头[标头键]}
{isSortable && sortersData![headerKey] !== 未定义 && (
<div
className="排序图标"
onClick={() => handleSortToggled(headerKey, sortersData![headerKey])}
>
{sortersData![headerKey]? <>∧</> : <>∨</> }
</div>
)}
</th>
)
}
const Row: FunctionComponent<{ row: TableConfig.Row }> = ({ row }) => {
返回 (
<tr>
{Object.values(row).map((cell: string, cellIndex: number) => (
<td key={'cell' + cellIndex}>{细胞}</td>
))}
</tr>
)
}
常量表:函数组件<TableConfig.TableProps>= ({
标头,
行,
排序,
}) => {
const isSortable = Boolean(sorters)
const [displayedRows, setDisplayedRows] = useState(rows)
const [sortersData, setSortersData] = useState(sorters)
const [currentSort, setCurrentSort] = useState('')
使用效果(()=> {
if (!isSortable || currentSort === '') {
返回
}
常量 sortedRows = rows.sort(
(一个记录<string, string>, b: 记录<string, string>) => {
if (sortersData![currentSort]) {
返回 a[currentSort] < b[currentSort] ? 1:-1
} else if (!sortersData![currentSort]) {
返回 a[currentSort] > b[currentSort] ? 1:-1
}
返回 0
},
)
setDisplayedRows([...sortedRows])
},[排序数据])
const handleSortToggled = (headerKey: string, isAsc: boolean) => {
如果(!isSortable){
返回
}
常量 newIsAsc = !isAsc
sortersData![headerKey] = newIsAsc
设置当前排序(标题键)
setSortersData({ ...sortersData })
}
返回 (
<>
<TableContext.Provider
value={{ 标题,isSortable,sortersData,handleSortToggled }}
>
<table>
<thead>
<tr>
{Object.keys(headers).map((headerKey: string, index: number) => (
<Header headerKey={headerKey} key={'col' + index} />
))}
</tr>
</thead>
<tbody>
{displayedRows.map((行:记录<string, string>, 索引: 数字) => (
<Row key={'row' + index} row={row} />
))}
</tbody>
</table>
</TableContext.Provider>
</>
)
}
导出默认表
3. 用于缩放和可读性的自定义钩子
所以我们可以扩展类型和 JSX。最后一个元素要移动。这是状态和与状态一起工作的方法。最好将它们移动到自定义挂钩。让我们看看它是什么样子的:
导入反应,{
创建上下文,
功能组件,
使用上下文,
使用效果,
使用状态,
} 从“反应”
导入'./Table.css'
从 './TableConfig' 导入 { TableConfig }
从 './useSorter' 导入 { useSorter }
常量表上下文 = 创建上下文<Record<string, any> >({})
常量头:FunctionComponent<{ headerKey: string }> = ({ headerKey }) => {
const { headers, isSortable, sortersData, handleSortToggled } = useContext(
表上下文,
)
返回 (
<th>
{标头[标头键]}
{isSortable && sortersData![headerKey] !== 未定义 && (
<div
className="排序图标"
onClick={() => handleSortToggled(headerKey, sortersData![headerKey])}
>
{sortersData![headerKey]? <>∧</> : <>∨</> }
</div>
)}
</th>
)
}
const Row: FunctionComponent<{ row: TableConfig.Row }> = ({ row }) => {
返回 (
<tr>
{Object.values(row).map((cell: string, cellIndex: number) => (
<td key={'cell' + cellIndex}>{细胞}</td>
))}
</tr>
)
}
常量表:函数组件<TableConfig.TableProps>= ({
标头,
行,
排序,
}) => {
const [displayedRows, setDisplayedRows] = useState(rows)
const [sortedRows, isSortable, sortersData, sortToggled] = useSorter(
行,
排序,
)
使用效果(()=> {
setDisplayedRows([...sortedRows])
}, [sortedRows])
const handleSortToggled = (headerKey: string, isAsc: boolean) => {
sortToggled(headerKey, isAsc)
}
返回 (
<>
<TableContext.Provider
value={{ 标题,isSortable,sortersData,handleSortToggled }}
>
<table>
<thead>
<tr>
{Object.keys(headers).map((headerKey: string, index: number) => (
<Header headerKey={headerKey} key={'col' + index} />
))}
</tr>
</thead>
<tbody>
{displayedRows.map((行:记录<string, string>, 索引: 数字) => (
<Row key={'row' + index} row={row} />
))}
</tbody>
</table>
</TableContext.Provider>
</>
)
}
导出默认表
从“反应”导入 { useEffect, useState }
从 './TableConfig' 导入 { TableConfig }
类型 SorterProps = [
TableConfig.Row[],
布尔值,
TableConfig.Sorter |不明确的,
(headerKey: string, isAsc: boolean) => void,
]
导出 const useSorter = (
行:TableConfig.Row[],
排序?:TableConfig.Sorter,
): 排序属性 => {
const isSortable = Boolean(sorters)
const [sortedRows, setSortedRows] = useState(rows)
const [sortersData, setSortersData] = useState(sorters)
const [currentSort, setCurrentSort] = useState('')
使用效果(()=> {
if (!isSortable || currentSort === '') {
返回
}
常量 sortedRows = rows.sort(
(一个记录<string, string>, b: 记录<string, string>) => {
if (sortersData![currentSort]) {
返回 a[currentSort] < b[currentSort] ? 1:-1
} else if (!sortersData![currentSort]) {
返回 a[currentSort] > b[currentSort] ? 1:-1
}
返回 0
},
)
setSortedRows([...sortedRows])
},[排序数据])
const sortToggled = (headerKey: string, isAsc: boolean) => {
如果(!isSortable){
返回
}
常量 newIsAsc = !isAsc
sortersData![headerKey] = newIsAsc
设置当前排序(标题键)
setSortersData({ ...sortersData })
}
返回 [sortedRows, isSortable, sortersData, sortToggled]
}
我们设法将组件的大小减少了近 40%!在这种情况下,如果您将子组件从文件中移出,您可以获得更好的结果。
另请阅读:
阅读我们 电报 , VK 和 Yandex.Zen
文章翻译 维塔利·舍夫丘克 : 前 3 个 React 技巧 Pros 喜欢用来减小组件的大小
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明