如何减小 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.划分子组件和共享状态

至此,我们知道类型、常量和辅助函数可以移动到哪里。现在我们弄清楚如何处理子组件。这些是主要大组件被拆分成的小子组件。应考虑两个特点。

  1. 始终在主组件的主体之外创建子组件,无论是在同一个文件中还是在其他文件中。否则,会出现性能问题,并且每次更新状态时都会创建子组件。
  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 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/38134/24092011

posted @ 2022-09-20 11:25  哈哈哈来了啊啊啊  阅读(131)  评论(0编辑  收藏  举报