带有 React Hooks 的可重用下拉菜单 [英] Reusable Dropdown with React Hooks

查看:50
本文介绍了带有 React Hooks 的可重用下拉菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如我从 React 文档中了解到的,使用钩子不需要大量代码重构,并且可以轻松包含在现有代码中.我想制作可重用的下拉菜单,从 react 组件渲染方法调用.这是我的代码:

As I got from React documentation using hooks do not require big code refactoring and can be easily included in the existing code. I want to make reusable dropdowns, being called from react component render method. Here is my code:

//navigation.js
import {DropdownToggler} from './dropdown.js';
export class ErrorTriangle extends Component {
   render(){
     return(
        {DropdownToggler({uiElement: {
            toggler: <img src={MyImg}/>,
            field: <div className={'errorMessage'}>
                       <p>Dropdown content</p>
                   </div >
        }})
       }
     )
   }
}

//dropdown.js
import React, {useEffect, useRef, useState} from "react";
import {store} from "../api/redux/store";

const DropdownToggler = (props) => {
    const myRef = useRef(null);
    const [showField, setShow] = useState(false);
    const isMobile = store.getState().isMobile;

   const remove = (e) => {
    e.stopPropagation();

    if (myRef && myRef.current.contains(e.target)) {
        return
    }
    setShow(false);
    if (isMobile===true) {
        document.removeEventListener('touchend', remove, false)
    } else {
        document.removeEventListener('mouseup', remove, false)
    }
};

const show = (e) => {
    e.stopPropagation();
    if (showField) {
        return
    }
    setShow(true);
    if (isMobile===true) {
        document.addEventListener('touchend', remove, false)
    } else {
        document.addEventListener('mouseup', remove, false)
    }
};

return (
    <>
        {React.cloneElement(props.uiElement.toggler, {
            onTouchEnd: (e) => show(e),
            onMouseUp: isMobile ? null : (e) => show(e)
        })}

        {showField ? React.cloneElement(props.uiElement.field, {ref: node => myRef.current= node}) : null}
    </>
)
};
export {DropdownToggler};

并得到错误:Hooks 只能在函数组件的主体内被调用.我已经检查了有关此问题的现有信息:

And get the error: Hooks can only be called inside the body of a function component. I have already checked existing information about this issue:

  1. react-hot-loader 版本是 4.8.0
  2. 我的 react 和 react-dom 都是 16.8.4 版本;
  3. 我的 babel-config 包含:

  1. react-hot-loader version is 4.8.0
  2. My react and react-dom are same version 16.8.4;
  3. My babel-config contains:

'use strict';

module.exports = {
   presets: ['@babel/preset-env', '@babel/preset-react'],
   plugins: ["@babel/plugin-proposal-class-properties", "jsx-control-statements", "react-hot-loader/babel"],
};

也许问题是我违反了钩子的规则 https://reactjs.org/warnings/invalid-hook-call-warning.html.将欣赏详细的解释(示例)或想法为什么这不起作用.

Maybe the problem is that I am breaking the rules of hooks https://reactjs.org/warnings/invalid-hook-call-warning.html. Will appreciate detailed explanations (examples) or ideas why this is not working.

推荐答案

更改

export class ErrorTriangle extends Component {
   render(){
     return(
        {DropdownToggler({uiElement: {
            toggler: <img src={MyImg}/>,
            field: <div className={'errorMessage'}>
                       <p>Dropdown content</p>
                   </div >
        }})
       }
     )
   }
}

export function ErrorTriangle (props) {
     return(
        {DropdownToggler({uiElement: {
            toggler: <img src={MyImg}/>,
            field: <div className={'errorMessage'}>
                       <p>Dropdown content</p>
                   </div >
        }})
       }
     )
}

改变

{DropdownToggler({uiElement: {
            toggler: <img src={MyImg}/>,
            field: <div className={'errorMessage'}>
                       <p>Dropdown content</p>
                   </div >
        }})
       }

{<DropdownToggler uiElement={{
    toggler: <img src={MyImg}/>,
    field: <div className={'errorMessage'}>
                <p>Dropdown content</p>
            </div >
  }}/>
}

说明

简单地说,如果您正在使用类,您应该像这样调用组件函数 而不是像普通函数 Component() 或您可以从使用类更改为使用组件函数

To put it simply if you are using class you should call your component function like this <Component /> and not like a normal function Component() or you can change from using class to using component function

这篇关于带有 React Hooks 的可重用下拉菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆