У меня есть компонент Table, к которому я хочу подключить ref.
Использование: Table.js
class Table extends React.Component {
constructor(props) {
super(props);
this.state = {
rows: 1,
dataLength: props.dataLength,
}
this.tableRef = React.createRef();
}
componentDidUpdate() {
//using ref
this.tableRef.current ..... //logic using ref
this.state.rows ..... //some logic
}
render() {
<TableContainer ref = {this.tableRef} />
<CustomPagination />
}
}
Это работает нормально, но теперь мои требования изменились, и я хочу повторно использовать компонент Table с разбивкой на страницы, применяемой ко всем таблицам в моем приложении. Решил сделать HOC withCustomPagination.
Использование: withCustomPagination.js HOC
import CustomPagination from 'path/to/file';
const withCustomPagination = tableRef => Component => {
return class WithCustomPagination extends React.Component {
constructor(props) {
super(props);
this.state = {
rows: 1,
dataLength: props.dataLength,
}
}
componentDidUpdate() {
tableRef.current.state ..... //logic using ref, Error for this line
this.state.rows ..... //some logic
}
render() {
return (
<Component {...state} />
<CustomPagination />
)
}
}
}
export default withCustomPagination;
Новый Table.js:
import withCustomPagination from '/path/to/file';
const ref = React.createRef();
const Table = props => (
<TableContainer ref = {ref} />
);
const WrappedTable = withCustomPagination(ref)(Table);
HOC withCustomPagination возвращает класс WithCustomPagination, который имеет метод жизненного цикла componentDidUpdate, который использует ссылку на таблицу в логике. Поэтому я пытаюсь передать ref, созданный в Table.js, в качестве аргумента для withCustomPagination, т.е. каррированный с помощью компонента без сохранения состояния ref и Table.
Это использование ref неверно, и я получаю сообщение об ошибке: TypeError: Cannot read property 'state' of null.
Я пробовал использовать Пересылка ссылок, но не смог.
Как передать таблицу ref в withCustomPagination и использовать ее в HOC?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Либо реструктурируйте свой код, чтобы не использовать для этого HOC, либо попробуйте использовать React.forwardRef:
Refs Aren’t Passed Through
While the convention for higher-order components is to pass through all props to the wrapped component, this does not work for refs. That’s because ref is not really a prop — like key, it’s handled specially by React. If you add a ref to an element whose component is the result of a HOC, the ref refers to an instance of the outermost container component, not the wrapped component.
The solution for this problem is to use the React.forwardRef API (introduced with React 16.3). Learn more about it in the forwarding refs section.
через Компоненты высшего порядка: ссылки не проходят
В раздел переадресации ссылок есть примеры кода, которые вы могли бы использовать для передачи refs вниз, но попытка поднять их в вашем случае не удастся:
Warning: Stateless function components cannot be given refs. Attempts to access this ref will fail.
В проекте мы использовали другой подход. Есть компонент EnhancedTable, который обрабатывает всю логику разбиения на страницы и сам по себе имеет компонент «тупой таблицы» и компонент разбивки на страницы. Он работает довольно хорошо, но это означает, что вам придется сверлить реквизиты (или использовать библиотеку хранилища, такую как Redux или Mobx) и добавлять новые, которые будут обрабатывать параметры разбивки на страницы. Это приведет к некоторому рефакторингу использования Table, и вам придется быть более точным, но я бы воспринял это как благо, а не как препятствие.
В этом случае вы можете использовать useImperativeHandle
Это означает, что вам нужно переслать ref и указать, какую функцию или объект или ...
вы хотите поделиться с ref внутри своего функционального компонента.
Вот мой пример Hoc:
import React from 'react';
import { View } from 'react-native';
export function CommonHoc(WrappedComponent) {
const component = class extends React.Component {
componentDidMount() {
this.refs.myComponent.showAlert();
}
render() {
return (
<>
<WrappedComponent
ref='myComponent'
{...this.state}
{...this.props}
/>
</>
);
}
};
return component;
}
и это мой компонент без состояния
const HomeController=(props,ref)=> {
useImperativeHandle(ref, () => ({
showAlert() {
alert("called");
},
}));
return (
<Text>home</Text>
);
};
export default CommonHoc(forwardRef(HomeController));
Мне удалось решить аналогичную проблему, которая привела меня к этой теме, без использования forwardRef или useImperativeHandle.
Создав ссылку на более высоком уровне и передав ее в компоненты и подкомпоненты, которые мне нужно было действовать с помощью ссылки.
/** Parent Component has access to ref and functions that act on ref **/
import { useRef } from 'react';
const formRef = useRef(); // ref will have dom elements need accessing
const onClickFunction=()=>{ //sample function acts on ref
var inputs = formRef.current.querySelectorAll('input')
/* Act on ref here via onClick function, etc has access to dom elements
in child component and childs child components */
};
return(
<ComponentGetsAttachedRef formRef = {formRef} />
//^ref sent down to component and its children
<ComponentNeedingRef onClickFunction = {onClickFunction}/>
//^function with access to ref sent down to component
)
/** Child component needs to act on ref**/
export const ComponentNeedingRef = ({ onClickFunction}) =>{
return(
<button onClick = {onClickFunction}>
)
}
/* Child component recieves ref and passes it down */
export const ComponentGetsAttachedRef = ({ formRef}) =>{
//ref comes in as prop gets attached to props or utilized internally
return (
<ChildsChildComponent formRef = {formRef}/> //sub component passed ref down
)
}
Не могли бы вы предоставить обновленный ответ для нового решения на основе React.createRef ().