在 ag 网格回调中使用状态变量不更新
Use state variable in ag grid callback not updating
我在函数 isExternalFilterPresent
内使用的状态变量 query
从不更新。我很困惑,因为 query
中的第一个 console.log
会随着查询的每次更改而更新。我想这是因为我不太了解hooks的实现。
let gridApi: GridApi | null = null;
const HouseholdTable = ({accountsData, aggregateEntityTable: {aggregateEntity, columnDefs}}: OwnProps & StateProps) => {
const [isDeepDiveOpen, setIsDeepDiveOpen] = useState(false);
const [query, setQuery] = useState('');
useEffect(() => {
gridApi && gridApi.onFilterChanged();
}, [query]);
if (accountsData) {
const onGridReady = ({api}: GridReadyEvent) => {
api.sizeColumnsToFit();
gridApi = api;
};
const aggData = accountsData.aggregations[aggregateEntity];
console.log(query); // This updates when query changes
const isExternalFilterPresent = (): boolean => {
console.log(query); // This never updates
return !!query;
};
const doesExternalFilterPass = (rowNode: RowNode): boolean => {
// console.log('doesExternalFilterPass');
return true;
};
return (
<>
<HouseholdsToolbar aggData={aggData}
isDeepDiveOpen={isDeepDiveOpen}
onDeepDiveToggleClick={setIsDeepDiveOpen}
onQueryChange={setQuery}
/>
<AgGridReact rowData={[]}
columnDefs={[]}
gridOptions={{
headerHeight: 70,
suppressFieldDotNotation: true,
suppressHorizontalScroll: false,
onGridReady,
isExternalFilterPresent,
doesExternalFilterPass
}}
/>
</>
);
} else {
// handle loading
return (<div>loading</div>);
}
};
const mapStateToProps = (state: StoreState): StateProps => {
const {faStore: {accountsData}} = state;
return {
accountsData,
aggregateEntityTable: aggregateEntityTableDummyConfig
};
};
export default connect(mapStateToProps)(HouseholdTable);
export const aggregateEntityTableDummyConfig: AggregateEntityTable = {
aggregateEntity: 'FOO',
columnDefs: []
};
编辑:更新了整个组件。
不是钩子的问题。看起来在第一次渲染时 AgGridReact
存储了对传递给 isExternalFilterPresent
的函数的引用,然后在重新渲染时永远不会更改此引用。更清楚地说,AgGridReact
存储 isExternalFilterPresent
的第一个 'version' 并且从不更新它。要解决您的问题,您需要将过滤器的值存储在 useRef
挂钩中。
React 文档 says:
The useRef() Hook isn’t just for DOM refs. The “ref” object is a generic container whose current property is mutable and can hold any value, similar to an instance property on a class.
因此您可能会像 class 中的 属性 一样考虑 useRef。
这是你必须做的:
const query = useRef(null);
const setQuery = (value) => {
query.current = value;
gridApi && gridApi.onFilterChanged();
}
const isExternalFilterPresent = (): boolean => {
console.log(query.current); // Now it changes
return !!query.current;
};
这里有一个关于 codesandbox
的例子
我在函数 isExternalFilterPresent
内使用的状态变量 query
从不更新。我很困惑,因为 query
中的第一个 console.log
会随着查询的每次更改而更新。我想这是因为我不太了解hooks的实现。
let gridApi: GridApi | null = null;
const HouseholdTable = ({accountsData, aggregateEntityTable: {aggregateEntity, columnDefs}}: OwnProps & StateProps) => {
const [isDeepDiveOpen, setIsDeepDiveOpen] = useState(false);
const [query, setQuery] = useState('');
useEffect(() => {
gridApi && gridApi.onFilterChanged();
}, [query]);
if (accountsData) {
const onGridReady = ({api}: GridReadyEvent) => {
api.sizeColumnsToFit();
gridApi = api;
};
const aggData = accountsData.aggregations[aggregateEntity];
console.log(query); // This updates when query changes
const isExternalFilterPresent = (): boolean => {
console.log(query); // This never updates
return !!query;
};
const doesExternalFilterPass = (rowNode: RowNode): boolean => {
// console.log('doesExternalFilterPass');
return true;
};
return (
<>
<HouseholdsToolbar aggData={aggData}
isDeepDiveOpen={isDeepDiveOpen}
onDeepDiveToggleClick={setIsDeepDiveOpen}
onQueryChange={setQuery}
/>
<AgGridReact rowData={[]}
columnDefs={[]}
gridOptions={{
headerHeight: 70,
suppressFieldDotNotation: true,
suppressHorizontalScroll: false,
onGridReady,
isExternalFilterPresent,
doesExternalFilterPass
}}
/>
</>
);
} else {
// handle loading
return (<div>loading</div>);
}
};
const mapStateToProps = (state: StoreState): StateProps => {
const {faStore: {accountsData}} = state;
return {
accountsData,
aggregateEntityTable: aggregateEntityTableDummyConfig
};
};
export default connect(mapStateToProps)(HouseholdTable);
export const aggregateEntityTableDummyConfig: AggregateEntityTable = {
aggregateEntity: 'FOO',
columnDefs: []
};
编辑:更新了整个组件。
不是钩子的问题。看起来在第一次渲染时 AgGridReact
存储了对传递给 isExternalFilterPresent
的函数的引用,然后在重新渲染时永远不会更改此引用。更清楚地说,AgGridReact
存储 isExternalFilterPresent
的第一个 'version' 并且从不更新它。要解决您的问题,您需要将过滤器的值存储在 useRef
挂钩中。
React 文档 says:
The useRef() Hook isn’t just for DOM refs. The “ref” object is a generic container whose current property is mutable and can hold any value, similar to an instance property on a class.
因此您可能会像 class 中的 属性 一样考虑 useRef。
这是你必须做的:
const query = useRef(null);
const setQuery = (value) => {
query.current = value;
gridApi && gridApi.onFilterChanged();
}
const isExternalFilterPresent = (): boolean => {
console.log(query.current); // Now it changes
return !!query.current;
};
这里有一个关于 codesandbox
的例子