Поигрался с новым хуком RFC в React и не могу заставить свой собственный хук работать должным образом. Не уверен, что то, что происходит, на моей стороне, или это ошибка самой React alpha.
Я пытался создать крючок за пределами клика. Я смог заставить его работать с этим кодом.
./dropdown_builtin_hooks
const DropDownWrapper = React.memo(props => {
const { user, className } = props;
const ref = useRef(null);
const [active, setActive] = useState(false);
useEffect(() => {
const handleDOMClick = event => {
console.log(event.target);
if (active && !!ref && !(event.target === ref.current || ref.current.contains(event.target))) {
console.log("Clicked outside of wrapped component");
setActive(false);
}
};
window.addEventListener("click", handleDOMClick);
return () => {
window.removeEventListener("click", handleDOMClick);
};
});
const handleDropDown = (): void => {
setActive(true);
};
return (
<div ref={ref} className={className} >
<Toggler onClick={handleDropDown}>
{active ? (
<StyledDropUpArrow height="1.5em" filled={false} />
) : (
<StyledDropDownArrow height="1.5em" filled={false} />
)}
</Toggler>
{active && (
<DropDown/>
)}
</div>
);
});
export default DropDownWrapper;
Однако, когда я пытаюсь обернуть это в пользовательский хук, я могу повторно использовать и импортировать его в свой компонент. Что-то вроде этого...
./hooks
export function useClickedOutside<RefType = any>(
initialState: boolean = false,
): [React.RefObject<RefType>, boolean, Function] {
const ref = useRef(null);
const [active, setActive] = useState(initialState);
useEffect(() => {
const handleDOMClick = event => {
console.log(event.target);
if (active && !!ref && !(event.target === ref.current || ref.current.contains(event.target))) {
console.log("Clicked outside of wrapped component");
setActive(false);
}
};
window.addEventListener("click", handleDOMClick);
return () => {
window.removeEventListener("click", handleDOMClick);
};
});
return [ref, active, setActive];
}
./dropdown_custom_hook
const DropDownWrapper = React.memo(props => {
const { user, className } = props;
const [ref, active, setActive] = useClickedOutside(false);
const handleDropDown = (): void => {
setActive(true);
};
return (
<div ref={ref} className={className} >
<Toggler onClick={handleDropDown}>
{active ? (
<StyledDropUpArrow height="1.5em" filled={false} />
) : (
<StyledDropDownArrow height="1.5em" filled={false} />
)}
</Toggler>
{active && (
<DropDown/>
)}
</div>
);
});
export default DropDownWrapper;
Сначала я подумал, что это проблема с горячей перезагрузкой, но после ее удаления я все еще получаю эту ошибку:
Неперехваченная ошибка: ловушки можно вызывать только внутри тела функционального компонента.
У меня эта проблема возникает только тогда, когда я использую импорт и экспорт. Если я скопирую ту же настраиваемую функцию перехвата и вставлю ее над своим компонентом, она будет работать правильно.
Я предполагаю, что делаю что-то глупое или недостаточно хорошо прочитал документацию.
Ваше здоровье
useEffect
,useRef
прямо в своей функции, но вне функционального компонента. Я считаю, что вы просто не можете этого сделать. Поэтому вам нужно перекомпоновать повторно используемую часть по-другому, чтобы она содержала только бизнес-логику, но не взаимодействие между разными хуками. - person skyboyer   schedule 30.10.2018react
, иreact
dom - правильная версия. Вчера вечером, когда я вернулся из офиса, поиграл еще, и этот код работал в новом проекте React. Я полагаю, что есть проблема с одной из моих зависимостей проекта. - person Zach   schedule 30.10.2018styled-components
иtypescript
, но я не могу воспроизвести эту ошибку, кроме как в моей кодовой базе. Я использовал недавно выпущенныйtypescript create-react-app
и добавилstyled-components
, но он там работает. Я думаю, что в моемbabelrc
илиwebpack configs
должно быть что-то, что вызывает проблему. Моя интуиция подсказывает мне, что это связано с этой проблемой или другой упомянутой проблемой, но я не могу воспроизвести ошибку в песочнице, чтобы сделать меня проблемой ???? - person Zach   schedule 30.10.2018