【问题标题】:Is it possible to pass a React.hook to a function?是否可以将 React.hook 传递给函数?
【发布时间】:2019-03-01 16:23:19
【问题描述】:

我可以将 React.hooks 传递给一个函数并在那里使用它吗?

    const [X, setX] = useState('');

    function  Y(useX){
       useX('string');
    }
    Y(setX)

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    使用钩子时,一定要遵守一定的hook rules(目前只有两个):

    1. 仅在顶层调用 Hooks
    2. 仅调用来自 React 函数的挂钩

    通过尝试将钩子传递给常规函数你同时违反了它们。虽然这些规则更多的是约定,而不是实际的限制,并且在某些情况下可能会起作用(正如该线程中的其他人所提到的)(您知道在哪里以及为什么可以使用它们,或者您意外满足了它们的使用要求不建议以这种方式使用它们。例如,一段时间后您可能会忘记您的函数包含一个钩子,并且实际上取决于声明和使用它的位置和方式,然后将其移动或放入条件中,从而有效地破坏了您的应用程序的逻辑。

    React 人员想出了专用的ESlint plugin 非常重要,它旨在在后台分析您的代码并在您接近违反钩子规则时准确地警告您。这是确定的方法。

    如果您仍需要从组件中提取一些依赖于钩子的逻辑到单独的函数中,请考虑创建一个custom hook

    但是!

    在您的示例代码中,您没有将挂钩传递给函数。 React.useState 是一个钩子,但它返回的 setX 不是。 您可以随心所欲地传递它,实际上您应该将它传递到您自定义的常规函数​​或自定义钩子!

    【讨论】:

    • 我有code,我在哪里使用了钩子,因此我的代码变得有点大,是否可以这样拆分code。在编程方面是否正确?
    • 是的,拆分代码实际上是一种最佳实践,这就是函数式编程的全部意义所在。
    【解决方案2】:

    在这种情况下,传递的不是钩子而是 setter 函数,钩子限制不适用于Y(setX)。它不一定位于组件范围内:

    function  Y(setX){
      setX('string');
    }
    
    const Comp = () => {
      const [X, setX] = useState('');
      Y(setX);
      ...
    }
    

    根据使用情况,它可以从记忆中受益,例如,如果 () => Y(setX) 应该作为道具传递:

    const Comp = () => {
      const [X, setX] = useState('');
      const setY = useCallback(() => Y(setX), []);
      ...
    }
    

    【讨论】:

    • 据我了解,React.hooks可以这样使用link而且不会有问题吧?
    • 不会有问题的。 setD 可以作为回调传递,这在文档中有所提及。不过,此示例与问题不同,没有您描述的 Y 函数。
    【解决方案3】:

    正如规则所述,钩子只能在函数组件的顶部调用,不应有条件地调用,因此虽然从技术上讲,您可以将其作为函数的参数传递,但随后您需要执行立即生效

    所以

    const App = () => {
        const [X, setX] = React.useState('x');
    
        function Y(useX){
           useX('string');
        }
    
        Y(React.useState);
        
        return <div>Hello {X}</div>
    }
    
    ReactDOM.render(<App/>, document.getElementById('app'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
    <div id="app" />

    会好的。

    但下面的代码不起作用

    const App = () => {
        const [X, setX] = React.useState('x');
    
        function Y(useX){
           useX('string');
        }
        
        
        return <div>Hello {X} <button onClick={() => {Y(React.useState)}}>Click</button></div>
    }
    
    ReactDOM.render(<App/>, document.getElementById('app'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
    <div id="app" />

    因此你不应该以这种方式使用它,因为它可能会发生你稍后在函数调用中添加一些语句,因此钩子不会保留它的调用顺序

    需要维护 Hooks 调用的顺序,因为 React 依赖于 hooks 调用顺序来维护方法中使用的 hooks 队列并处理所有进一步的更新

    从技术上讲,如果useX 是一个自定义钩子,它本质上是一个函数 从顶部包含钩子的组件中调用 等级

    【讨论】:

    • 我有点困惑,我的代码能用吗?这种方式可以使用钩子吗?link
    • 是的,您的代码可以工作,但前提是您不有条件地调用函数 Y
    • 即函数不应该在IF运算符中?
    • 函数或函数调用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    • 2015-05-11
    • 2021-11-11
    • 1970-01-01
    相关资源
    最近更新 更多