是否可以将React.hook传递给函数?

时间:2019-03-01 16:23:20

标签: reactjs react-hooks

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

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

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

3 个答案:

答案 0 :(得分:3)

使用挂钩时,您必须遵守某些hook rules(目前只有两个):

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

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

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

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

但是!

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

答案 1 :(得分:1)

根据规则,钩子只能在功能组件的顶部调用,不应有条件地调用,因此从技术上讲,您可以将钩子作为函数的参数进行传递,但随后需要执行立即起作用

所以

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依赖于钩子调用顺序来维护该方法中使用的钩子队列并处理所有进一步的更新

  

从技术上讲,如果useX是一个自定义钩子,则它实际上是一个   从顶部包含钩子的组件中调用   级别

答案 2 :(得分:0)

在这种情况下,传递的不是钩子而是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), []);
  ...
}