【问题标题】:React: Handle dynamic refs with custom hookReact:使用自定义钩子处理动态引用
【发布时间】:2020-12-16 23:57:18
【问题描述】:

我正在构建一个严重依赖动画的应用,但在使用动态引用和自定义挂钩时遇到了一些麻烦。

所以,我有一个自定义钩子,它添加了一个点击事件侦听器、处理动画并返回一个引用。

const usePageChange = () => {
  const node = useRef(null);
  const tl = useMemo(() => gsap.timeline({ paused: true }), []);

  useEffect(() => {
    // Set GSAP timeline
    // omited for the sake of brevety
    return () => {
      tl.kill();
    };
  }, []);

  useEffect(() => {
    const set = (ev) => {
      ev.preventDefault();
      tl.play();
    };
    
    const { current } = node;
    current.addEventListener('click', set);

    return () => {
      current.removeEventListener('click', set);
    };
  }, [tl]);

  return node;
};

这适用于非动态的refs

const Home = () => {
  const elementRef = usePageChange();

  return (
    <div className='slides'>
      <img
        alt='some alt'
        src='/public/someimage.jpg'
        ref={elementRef}
      />
    </div>
  );
};

但我一直无法找到一种方法来使用动态refs 而不破坏Rules of Hooks

这是我尝试过的(简化的),但显然不正确。不能在回调中调用 React Hook:useRef(projects.map(() =&gt; usePageChange()));

const Home = () => {
  const projects = useSelector((state) => state.projects.data);

  const elementsRef = useRef(projects.map(() => usePageChange()));

  return (
    <div className='slides'>
      {projects.map((project, i) => (
        <img
          alt={`${project.image_alt}`}
          src={`/public/${project.image_path}`}
          ref={elementsRef[i]}
        />
      ))}
    </div>
  );
};

我真正需要的是一种以某种方式循环遍历项目长度并动态调用 usePageChange 钩子的方法。

此时不知道是不是直接给每个动态元素添加点击事件,在组件内部处理动画效果会更好。

【问题讨论】:

    标签: javascript reactjs react-hooks react-ref


    【解决方案1】:

    对于这样的事情,赋予每个列表项状态比尝试在父组件中维护某种子状态数组更有意义。

    const ProjectListItem = ({ project }) => {
      const elementRef = usePageChange();
    
      return (
        <img
          alt={`${project.image_alt}`}
          src={`/public/${project.image_path}`}
          ref={elementRef}
        />
      );
    }
    
    const Home = () => {
      const projects = ...;
    
      return (
        <div className='slides'>
          {projects.map(project => (
            <ProjectListItem project={project} />
          ))}
        </div>
      );
    };
    

    如果这对你不起作用,你可能想试试ref prop 的回调形式:

    const usePageChange = () => {
      const [node, setNode] = useState(null);
    
      // ...
    
      return { node, setNode };
    };
    
    const ProjectListItem = ({ project }) => {
      const { setNode } = usePageChange();
    
      return (
        <img
          alt={`${project.image_alt}`}
          src={`/public/${project.image_path}`}
          ref={setNode}
        />
      );
    }
    

    【讨论】:

    • 在单独的组件上处理它更有意义。感谢您的洞察和澄清!
    猜你喜欢
    • 2020-08-27
    • 2021-06-24
    • 1970-01-01
    • 2020-12-05
    • 2021-01-20
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多