众所周知,如果我们在Function Component
中使用useState
,状态不会每次在该函数组件re-renders
上创建,而是使用现有状态。请参阅下面的Example
函数组件:
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
当我们在customHook
中有一个useState
时(见下文),每次调用 "useCustomHook
" 都会产生一个新状态,这给出了一个想法,即所有自定义钩子都只是常规函数。
function useCustomHook() {
const [cnt, setCnt] = useState(0);
return [cnt, setCnt];
}
从下面的代码片段中可以看出,useState
调用在 customHook 中是持久的,就像它在常规组件中一样。您可以跟踪它,甚至可以操纵它。它不会在每个钩子调用中重新创建。
来自 React DOCS:自定义钩子
自定义钩子是自然遵循钩子设计的约定,而不是 React 功能。
我必须以"use"开头命名我的自定义钩子吗?
请做。这个约定非常重要。没有它,我们将无法自动检查是否违反 Hooks 规则,因为我们无法判断某个函数是否包含对 Hooks 的调用。
两个组件使用相同的 Hook 共享状态吗?
不。自定义 Hook 是一种重用有状态逻辑(例如设置订阅并记住当前值)的机制,但每次使用自定义 Hook 时,其中的所有状态和效果都是完全隔离的。
自定义 Hook 如何获得隔离状态?
每次调用 Hook 都会获得隔离状态。因为我们直接调用 useFriendStatus ,所以从 React 的角度来看,我们的组件只调用 useState 和 useEffect。正如我们之前所了解的,我们可以在一个组件中多次调用 useState 和 useEffect,它们将是完全独立的。
function App(){
const [hookState,setHookState] = useSomeCustomHook();
function updateHookState() {
setHookState((prevState)=>prevState+1);
}
return(
<React.Fragment>
<div>Custom Hook State: {hookState}</div>
<button onClick={updateHookState}>Count</button>
</React.Fragment>
);
}
function useSomeCustomHook() {
const [hookState,setHookState] = React.useState(0);
return ([
hookState,
setHookState
]);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<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="root"></div>