javascript - 在 React 函数式组件中声明静态变量的最佳方式是什么?
问题描述
在 React 功能组件中声明变量的最佳方式是什么(从现在开始 - RFC)?这与类似的问题不重复。
至于我,有几种声明变量的方法`
- 在 RFC中声明它
const
- 如果我们将它传递给HeavyComponent
组件,那么在每次渲染时,它都会创建一个新的引用,并且HeavyComponent
也会渲染。不是一个好的选择。 - 使用内部 RFC 声明
useRef
- 在随后的渲染中引用将是相同的,这很好,但另一方面,我们使用的是useRef
内部方法(函数调用 - 它在引擎盖下做了一些工作) - 在 RFC(外部范围)之外声明
const
- 在这种情况下,引用将再次相同,因为它将取自闭包并且我们不使用useRef
方法。但是,在这种特殊情况下,我们在外部范围内声明该变量并且它不会被垃圾收集并且会导致内存泄漏(如果我们经常使用这种情况)。
我知道,每种情况都有其优点和缺点。但是我们什么时候坚持使用某个选项呢?
更新 这里是例子
export const UnemployedEmployeesReportPaper = React.memo((props: IProps) => {
const [filterText, setFilterText] = useState('');
const [tableData, setTableData] = useState([]);
const headerColumns = useRef([
{ children: 'First Name', width: 240, flexGrow: 1, sortValue: item => item.FirstName },
{ children: 'Last Name', width: 240, flexGrow: 1, sortValue: item => item.LastName },
{ children: 'Last day of employment', width: 240, flexGrow: 1, sortValue: item => moment(item.Since).format('L') },
]).current;
const filterEmployee = (event: SyntheticEvent): void => {
const { value } = event.target;
const { payload } = props.unemployedEmployees;
const newTableData = payload.filter((row: ISimpleEmployeeRowData): boolean =>
(row.FirstName).toLowerCase().includes(value.toLowerCase()));
setTableData(newTableData);
setFilterText(value);
};
const rows = useMemo(() => {
return tableData.map(entry => {
return {
data: [
{ children: entry.FirstName },
{ children: entry.LastName },
{ children: entry.Since },
],
onDoubleClick: (): void => props.goToEmployees(entry.ID),
// Empty onClick will turn the hovering of table on
onClick: () => {}
};
});
}, [tableData]);
useEffect(() => {
if (props.unemployedEmployees.payload) {
setTableData(props.unemployedEmployees.payload);
}
setFilterText('');
}, [props.unemployedEmployees]);
return (
<VTable
sortable
striped
rowHeight={36}
headerColumns={headerColumns}
rows={rows}
/>);
});
Here is used useRef
,但我不确定它是否比在 RFC 之外声明它更好。
解决方案
将变量存储在功能组件中的最佳方式取决于您的用例。
在大多数情况下,您可以使用 useRef 钩子,因为它会在函数的每次渲染中返回相同的变量实例。
但是,您也可以使用 useMemo 挂钩定义变量并为其赋值。
喜欢
const val = useMemo(() => {
return some calculation based value or in general a normal value
},[]) // dependency array to recalculate value
您必须注意 useRef 可以帮助您解决闭包问题,并且当您想要使用受闭包影响的变量时会派上用场。例如,在 useEffect 中定义的 setInterval 函数中使用闭包中的值,并且具有空依赖项。
另一方面,useMemo 将帮助您防止每次重新渲染的变量的引用更改。一个常见的用例是为 ContextProvider 提供一个记忆值
更新:
对于您的用例,有两种方法可以定义 headerColumns。
在组件之外作为常数。当值预计不会改变时,将其声明为函数组件外部的常量是有意义的,也不需要使用闭包中的任何值
作为函数内的记忆值
const headerColumns = useMemo( () => [
{ children: 'First Name', width: 240, flexGrow: 1, sortValue: item => item.FirstName },
{ children: 'Last Name', width: 240, flexGrow: 1, sortValue: item => item.LastName },
{ children: 'Last day of employment', width: 240, flexGrow: 1, sortValue: item => moment(item.Since).format('L') },
], []);
当您使用闭包中的值时,您必须注意使用useMemo
分配值headerColumns
是有意义的。
推荐阅读
- sql - 用另一个表中的值替换返回的 ID
- amazon-web-services - 阶跃函数等待状态下的输出数据
- javascript - 链接两个元素,存储它们,并将它们发送到删除函数 - 纯 Javascript
- javascript - 如何从对象数组中获取 id 值?
- dialogflow-es - Dialogflow 从 webhook 更改表面
- r - 汇总数据帧以获得差异(滞后差异)
- matlab - 你如何创建一个 LLDB 脚本来忽略 SIGSEGV 和 SIGBUS
- sql - 如何加入 3 个表,根据条件限制查询,如果条件不满足则返回空列?
- mysql - Join 产生重复的行并忽略 Where 语句
- c - C 服务器程序无法分叉