React.forwardRef уже возможен и без него, так какой в этом смысл?
Я не понимаю, что такое React.forwardRef. Как объясняется в документации, я понимаю, что его основное использование - это получение родительским элементом доступа к элементам DOM дочернего элемента. Но я уже могу это делать, даже не используя его.
Вот пример кода, который вы можете подключить в codeSandbox и убедиться, что он работает:
import React, {useRef, useEffect} from "react";
import "./styles.css";
const ChildComponent = (props) => {
useEffect( ()=> {
props.callbackFunction()
})
return(
<div ref={props.fRef}>
{"hello"}
</div>
)
}
export default function App() {
const callbackFunction = () => {
console.log("The parent is now holding the forwarded ref to the child div: ")
console.log(forwardedRef)
}
const forwardedRef = useRef(null)
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<ChildComponent name="gravy" callbackFunction={callbackFunction} fRef={forwardedRef}/>
</div>
);
}
Или вот вставка этого примера. Честно говоря, я новичок в этом, и я точно не знаю, как работает встраивание, и изменяет ли кто-то, кто возится с встраиванием, мою исходную песочницу или нет, поэтому я не решился поставить это. Но вот оно. Пример пересылки Ref
В этом примере родительский компонент App() успешно передает ссылку дочернему элементу, который дочерний элемент прикрепляет к своему визуализированному div. После рендеринга он вызывает функцию обратного вызова для родителя. Затем родительский элемент ведет журнал консоли, в котором доказывает, что его перенаправленная ссылка теперь удерживает дочерний div. И все это делается без React.forwardRef.
Так в чем же тогда смысл React.forwardRef?
2 ответа
Вы абсолютно правы, что можете делать то, что описали. Обратной стороной является то, что вы вынуждены открывать API (то есть:fRef
prop), чтобы он работал. Не имеет большого значения, если вы являетесь индивидуальным разработчиком, создающим приложение, но это может быть более проблематичным, например. если вы поддерживаете библиотеку с открытым исходным кодом с общедоступным API.
В этом случае потребители библиотеки не будут иметь доступа к внутренним компонентам компонента, а это значит, что вам придется как-то раскрыть его для них. Вы можете просто сделать то, что вы предлагаете в своем примере, и добавить именованную опору. Фактически, это то, что библиотеки делали до React 16.3. Ничего страшного, но вам придется задокументировать это, чтобы люди знали, как им пользоваться. В идеале вам также нужен какой-то стандарт, который использовали бы все, чтобы это не сбивало с толку (многие библиотеки использовалиinnerRef
соглашение об именах), но по этому поводу должен быть некоторый консенсус. Так что все выполнимо, но, возможно, не идеальное решение.
С помощью forwardRef
передача ссылки компоненту работает должным образом. Вref
prop уже стандартизирован в React, поэтому вам не нужно смотреть документацию, чтобы понять, как передать ссылку вниз или как она работает. Однако подход, который вы описываете, абсолютно хорош, и, если он соответствует вашим потребностям, обязательно следуйте ему.
Как упоминалось в документации, он полезен для компонентов с высокой степенью повторного использования, то есть компонентов, которые обычно используются как обычные элементы HTML DOM.
Это полезно для библиотек компонентов, где у вас много "листовых" компонентов. Вы, наверное, использовали такой как Material UI.
Пример:
Допустим, вы поддерживаете библиотеку компонентов.
Вы создаете <Button/>
а также <Input/>
компонент, который, возможно, просто добавляет стиль по умолчанию.
Обратите внимание, что эти компоненты буквально похожи на обычные элементы HTML DOM с дополнительными шагами.
Если бы эти компоненты были созданы для использования как обычные элементы HTML DOM, то я ожидаю, что все реквизиты будут такими же, включая ref
нет?
Разве это не было бы утомительно, если бы получить ссылку на кнопку с вашего <Button/>
компонент, мне пришлось бы пройти через что-то вроде fRef
или buttonRef
?
То же самое с твоим <Input/>
, мне нужно обратиться к документации, чтобы узнать, какую ссылку использовать, и это что-то вроде inputRef
? Теперь надо запомнить?
Получение ссылки должно быть таким же простым, как <Button ref={}/>
Проблема
Как вы, возможно, знаете, ref
не будет проходить через реквизит, потому что, как и key
, React по-другому обрабатывает это.
Решение
React.forwardRef() решает эту проблему, поэтому я могу использовать <Button ref={}/>
или <Input ref={}/>
.