Intellij Idea 类型推断不适用于React.forwardRef()的引用参数

wrrgggsh  于 2024-01-05  发布在  React
关注(0)|答案(1)|浏览(133)

我正在尝试使用React.forwardRef(),我对以下问题感到困惑:


的数据
看起来IntelliJ能够正确地干扰引用的类型,在本例中是FilterRef
但是,我无法访问当前值ref.current,除非出现编译错误,说明该值不存在。
当然,在运行时将其打印出来可以确认current是一个现有属性。
不知道是什么原因导致这个问题。

代码

我正在创建一个引用,我想与Filter组件和上下文提供程序共享:

  1. const filterRef = useRef<FilterElement>({ filters, setFilters: onSetFilters });
  2. console.log('filterRef', filterRef);
  3. return (
  4. <>
  5. <Filter ref={filterRef} />
  6. <FilterContext.Provider value={{ ref: filterRef }}>
  7. <Outlet />
  8. </FilterContext.Provider>
  9. </>
  10. );

字符串
但是,current始终是null

  1. export const Filter = React.forwardRef<FilterElement, FilterProps>((props, ref) => {
  2. const filterRef = useRef<FilterElement>(null);
  3. useImperativeHandle(ref, () => filterRef.current!, []);
  4. console.log('filter', filterRef, ref);
  5. // ...
  6. }

ufj5ltwl

ufj5ltwl1#

编辑2

为了让Filter自己管理一个单独的状态,也可以执行以下操作:

  1. export const Filter = React.forwardRef<FilterElement | undefined, FilterProps>((props, ref) => {
  2. const [filters, setFilters] = useState<FilterItem[]>([]);
  3. const refInstance: FilterElement = useMemo(() => {
  4. return {
  5. filters,
  6. setFilters,
  7. };
  8. }, [filters]);
  9. useImperativeHandle(ref, () => refInstance, [refInstance]);
  10. // ...
  11. }

字符串

编辑:

根据更新的代码,我认为你根本不需要ref,因为你可以将filterssetFilters传递给Filter组件和FilterContext提供程序:

  1. <Filter filters={ filters } setFilters={ onSetFilters } />
  2. <FilterContext.Provider value={{ filters, setFilters: onSetFilters }}>
  3. <Outlet />
  4. </FilterContext.Provider>


在任何情况下,如果你想这样做,你不需要使用forwardRef,只要命名你的 prop 别的东西,并输入RefObject

  1. const App = () => {
  2. const filterRef = useRef<FilterElement>({ filters, setFilters: onSetFilters });
  3. return (
  4. <>
  5. <Filter filterRef={filterRef} />
  6. <FilterContext.Provider value={{ ref: filterRef }}>
  7. <Outlet />
  8. </FilterContext.Provider>
  9. </>
  10. );
  11. }
  12. export interface FilterProps {
  13. filterRef: RefObject<FilterElement>;
  14. }
  15. export const Filter: React.FC<FilterProps> = ({ filterRef }) => {
  16. console.log('filter', filterRef);
  17. // ...
  18. }


如果您想在Filter组件中使用ref,但又想将相同的ref暴露给父组件,则可以使用下面的useImperativeHandler答案。

原始答案:

Refs可以是一个带有current属性的对象,就像useRef返回的对象一样,也可以是一个ref回调函数,所以编译器是正确的。
您应该在Filter组件中创建一个新的ref,并使用useImperativeHandle将其与转发的组件同步:

  1. export const Filter = forwardRef<FilterRef, FilterProps>((props, ref) => {
  2. const filterRef = useRef(null);
  3. useImperativeHandle(ref, () => filterRef.current!, []);
  4. ...
  5. });

展开查看全部

相关问题