【问题标题】:Reusable Dropdown with React Hooks带有 React Hooks 的可重用下拉列表
【发布时间】:2019-03-07 21:43:42
【问题描述】:

正如我从 React 文档中得到的,使用钩子不需要大的代码重构,并且可以很容易地包含在现有代码中。我想制作可重用的下拉菜单,从反应组件渲染方法中调用。 这是我的代码:

//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 只能在函数组件的主体内部调用。 我已经检查了有关此问题的现有信息:

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

    '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 的规则。将感谢详细的解释(示例)或想法为什么这不起作用。

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    改变

    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 >
      }}/>
    }
    

    说明

    简单地说,如果你使用类,你应该像这样&lt;Component /&gt;而不是像普通函数Component()那样调用你的组件函数,或者你可以从使用类更改为使用组件函数

    【讨论】:

    • @ip 上述两种解决方案都应该有效。如果没有工作,请告诉我
    • 我知道第一个建议,但这不符合我的需要。第二个选项 - 工作正常!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-06
    • 2020-01-13
    • 2020-01-06
    • 2020-06-13
    • 2015-10-25
    • 2013-01-11
    • 1970-01-01
    相关资源
    最近更新 更多