Я просматривал документацию по хукам, когда наткнулся на нее useRef
.
Глядя на их пример…
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
… Вроде useRef
можно заменить на createRef
.
function TextInputWithFocusButton() {
const inputRef = createRef(); // what's the diff?
const onButtonClick = () => {
// `current` points to the mounted text input element
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
Зачем нужен хук для рефов? Почему useRef
существует?
источник
useRef
, опубликованную одним из разработчиков React. Это не то же самое, что простой вызовcreateRef
, посколькуcreateRef
это не ловушка и не сохраняется какое-либо состояние между вызовами. Ответ Райана Когсвелла также является хорошим примером различий.TLDR
A
ref
- простой объект JS{ current: <some value> }
.React.createRef()
фабрика возвращает реф{ current: null }
- никакой магии .
Достаточно использоватьuseRef(initValue)
также возвращает ссылку,{ current: initValue }
похожую наReact.createRef()
. Кроме того , он запоминает эту ссылку, чтобы она сохранялась при нескольких отрисовках в функциональном компоненте .React.createRef
в компонентах класса, поскольку объект ref назначается переменной экземпляра , следовательно, доступен для всего компонента и его жизненного цикла:this.myRef = React.createRef(); // stores ref in "mutable" this context (class)
useRef(null)
в основном эквивалентноuseState(React.createRef())[0]
1 .1 Заменить
useRef
наuseState
+createRef
Следующий твит был для меня поучительным:
Теперь, опираясь на информацию из
tldr
раздела, мы можем сделать следующий вывод:Вышеупомянутый код "злоупотребляет"
useState
сохранением возвращенного исхReact.createRef()
.[0]
просто выбирает часть значенияuseState
-[1]
будет установщиком.useState
вызывает повторную визуализацию в отличие отuseRef
. Более формально React сравнивает старую и новую ссылку на объектuseState
, когда новое значение устанавливается с помощью метода установки. Если мы мутировать состояниеuseState
непосредственно (не против сеттеров вызова), то его поведение более или менее становится эквивалентом кuseRef
, так как без повторного рендеринга срабатывают больше:// Example of mutaing object contained in useState directly const [ref] = useState({ current: null }) ref.current = 42; // doesn't cause re-render
Примечание: не делайте этого! Используйте оптимизированный
useRef
API вместо того, чтобы изобретать колесо. Выше для иллюстрации.источник
Просто чтобы выделить цель:
createRef
так же просто, какreturn {current: null}
. Это способ обрабатыватьref=
опору самым современным способом, и все (в то время как основанный на строках - это слишком магия, а на основе обратного вызова выглядит слишком многословно).useRef
сохраняет некоторые данные перед рендерингом, и их изменение не вызывает повторного рендеринга (как этоuseState
происходит). Они редко связаны. Все, что вы ожидаете от компонента на основе классов, переходит в поля экземпляра (this.* =
), похоже, кандидат для реализацииuseRef
в функциональных компонентах.Say
useCallback
работает как методы ограниченного класса (this.handleClick = .....bind(this)
) и может быть повторно реализован (но мы точно не должны изобретать колесо) с помощьюuseRef
.Другими примерами являются ссылки на DOM, идентификаторы тайм-аута / интервала, идентификаторы или ссылки любых сторонних библиотек.
PS Я считаю, что команде React лучше выбрать другое название,
useRef
чтобы избежать путаницыcreateRef
. Может бытьuseAndKeep
или дажеusePermanent
.источник
Еще одно, но важное дополнение к другим ответам.
Вы не можете установить новое значение для
createRef
. Но вы можетеuseRef
.const ur = useRef(); const cr = createRef(); ur.current = 10; // you can do it, and value is set cr.current = 10; // you can, but it's no good, it will not change it
источник
current
свойство как обычно (только что проверили). Неважно, создана ли ссылка черезuseRef
илиcreateRef
.