React Hooks - «Функциональным компонентам нельзя давать ссылки» с помощью useRef - PullRequest
0 голосов
/ 20 июня 2019

Я использую компоненты styled, FontAwesome и React Hooks, чтобы создать блок значков и меток (Box.js) для заголовка / панели навигации.Внутри коробки есть Container, в котором хранятся Icon и Label.Я хочу, чтобы и Icon, и Label меняли цвета вместе, когда вы наводите курсор на или из них, поэтому я добавляю onMouseOver и onMouseOut к компоненту Container.Я свободно следовал этому руководству , чтобы реализовать нечто подобное.

Перед тем как перейти по ссылке, я попробовал этот useHover ловушку, которая не выдала мне сообщение об ошибке, но не произвела никакого эффекта (даже вывод console.log, когда я завис над ней).

Я погуглил сообщение об ошибке, но похоже, что существующие сообщения StackOverflow и проблемы React на Github не связаны с хуками.Сообщения об ошибках, о которых сообщается в этих сообщениях, также немного отличаются: Warning: Stateless function components cannot be given refs. Attempts to access this ref will fail. В моем сообщении об ошибке нет слова «без состояний».

Рабочий пример здесь: https://codesandbox.io/s/q7rwe

Ожидается: все дочерние элементы Container (т. Е. Icon и Label) меняют цвет на зеленый, когда указатель мыши над любымодин дочерний элемент.

Факт: я получаю следующее сообщение об ошибке -

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of `Box`.
    in Icon (created by Box)
    in div (created by Context.Consumer)
    in StyledComponent (created by styled.div)
    in styled.div (created by Box)
    in Box (created by App)
    in div (created by App)
    in App

1 Ответ

1 голос
/ 20 июня 2019

В вашем текущем подходе есть несколько недостатков.

Прежде всего, вы не должны давать ref функциональному компоненту.

Но даже если вы это сделаете, вы не сможете использовать ref для изменения цвета с учетом вашей текущей структуры, потому что useEffect будет активирован после рендеринга и сразу же сделает цвет компонента зеленым, потому чтоref.current будет существовать.

У вас уже есть isHovered состояние.Просто используйте это для изменения цвета.

Я обновил ваш код, чтобы лучше реализовать желаемое поведение.Попробуйте!

Box.js

const Box = () => {
  const [isHovered, setHovered] = useState(false);

  return (
    <Container
      onMouseOver={() => setHovered(true)}
      onMouseOut={() => setHovered(false)}
    >
      <Icon isHovered={isHovered} />
      <Label isHovered={isHovered} />
    </Container>
  );
};

Icon.js

import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCoffee } from "@fortawesome/free-solid-svg-icons";
const Icon = props => {
  return (
    <FontAwesomeIcon
      icon={faCoffee}
      color={props.isHovered ? "green" : "black"}
    />
  );
};

export default Icon;

Label.js

import React from "react";
const Label = props => {
  return (
    <p style={{ color: props.isHovered ? "green" : "black" }}>
      Label goes here
    </p>
  );
};
export default Label;

https://codesandbox.io/embed/useref-error-xjf48

...