我已经看到React v16中引入了这两个新概念。
据我了解:
useState
与带有钩子的setState
类似,而useEffect
的工作原理类似于生命周期方法。
我的理解正确吗?如果没有,useState
和useEffect
之间的确切区别是什么?
答案 0 :(得分:5)
useState()
首先,我们有不支持的功能组件 state
,换句话说,功能组件是无状态组件。
现在,有了Hooks,我们有了功能组件,但是有状态。这可以通过使用useState来实现。
useEffect()
首先,对于无状态功能组件,我们没有组件生命周期挂钩。换句话说,每当要使用组件生命周期挂钩时,都应考虑使用类组件。
现在,我们可以使用组件生命周期挂钩,而无需使用类组件。通过使用useEffect来实现。换句话说,现在无论何时我们想使用组件生命周期钩子,我们都已经有了使用 class component 或将钩子与useEffect
一起使用的两个选择。
更新
useState
和useEffect
之间的确切区别是什么?
简而言之,useState
使我们以前无状态的功能组件变为有状态。并且useEffect
允许我们的功能组件利用组件生命周期挂钩,而这些挂钩过去仅受 class组件支持。 / p>
答案 1 :(得分:4)
简而言之,useState
和useEffect
都增强了功能组件,以使它们执行类可以但功能组件(不带钩子)不能执行的操作:
useState
允许功能组件具有状态,例如类组件中的this.state
。useEffect
允许功能组件在单个API中具有生命周期方法(例如componentDidMount
,componentDidUpdate
和componentWillUnmount
)。请参考以下示例以进一步说明:
useState
class CounterClass extends React.Component {
constructor(props) {
super(props);
this.state = { count: 1 };
}
render() {
return <div>
<p>Count: {this.state.count}</p>
<button onClick={() => this.setState({
count: this.state.count + 1
})}>Increase</button>
</div>;
}
}
function CounterFunction() {
const [count, setCount] = React.useState(1);
return (
<div>
<p>Count: {count}</p>
<button onClick={() =>
setCount(count + 1)}
>Increase</button>
</div>
);
}
ReactDOM.render(
<div>
<CounterClass />
<CounterFunction />
</div>
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
useEffect
class LifecycleClass extends React.Component {
componentDidMount() {
console.log('Mounted');
}
componentWillUnmount() {
console.log('Will unmount');
}
render() {
return <div>Lifecycle Class</div>;
}
}
function LifecycleFunction() {
React.useEffect(() => {
console.log('Mounted');
return () => {
console.log('Will unmount');
};
}, []); // Empty array means to only run once on mount.
return (
<div>Lifecycle Function</div>
);
}
ReactDOM.render(
<div>
<LifecycleClass />
<LifecycleFunction />
</div>
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
答案 2 :(得分:3)
useState
和useEffect
是React 16.8+钩子生态系统的一部分,该生态系统旨在为功能组件提供以前仅基于类的组件(state
/ {{1 }}和组件生命周期方法(例如setState
,componentDidMount
和componentDidUpdate
)
componentWillUnmount
很简单,它使您可以在功能组件中使用状态访问器。
useState()
可以组合useEffect()
,componentDidMount
和componentDidUpdate
,但是很棘手。
您可以从hooks的官方文档中了解我在这里要讨论的大部分内容。看到钩子在起作用,比从文本中推论要容易得多。
componentWillUnmount
或componentWillReceiveProps
和getDerivedStateFromProps
的 预渲染生命周期事件可能只是我们在返回JSX之前在功能组件中首先要做的事情(该函数本身相当于基于类的组件的componentWillMount
方法。
我们不需要处理预渲染生命周期事件的钩子。
渲染后生命周期事件,它们等同于基于类的组件中的render(…)
,componentDidMount
和componentDidUpdate
。
我们需要 ** componentDidUnmount
以处理这些渲染后生命周期事件 **,因为我们无法编写与主要组件功能内的这些生命周期事件相关联的逻辑,因为这些事件应该在组件功能将JSX(反应节点)返回到**_useEffect(…)_**
渲染器之后运行。
这意味着,钩子可以做很多事情。怎么样?
我们知道react-dom
,有两个参数。
useEffect(fn, […watchStates])
:(必需)fn
调用此函数以在每个渲染周期之后根据(2)参数给出的更改跟踪值来作为副作用运行。函数useEffect
可能会返回另一个函数,该函数应在效果函数再次运行或卸载组件之前作为清理运行。fn
:(可选)[…watchValues ]
跟踪此数组中的值自上一个渲染周期以来已更改,然后仅调用效果useEffect
。如果未指定此参数,则效果将在每个渲染周期运行。如果我们未完全传递(2)参数,则fn
中的效果逻辑将在每个渲染周期后调用。
如果我们传递带有值的(2)数组,则组件需要监视更改,并在更改时调用fn
,这很容易说明。
最棘手的部分是使用空数组fn
作为(2)参数,我们可以限制[]
中的副作用逻辑仅在安装阶段执行,因为没有更改效果钩子将在后续渲染周期后再次触发fn
的情况下进行监视。
fn
该代码段简单易懂。您可以在CodePen上试用。
要注意的一件事是,如果要在效果内部进行状态更改,请确保从监视数组中排除内部正在更改的状态。
例如,在第二个效果(用于计算鼠标移动的效果)中,我们仅通过将import React, { useState, useEffect } from "react";
export default props => {
console.log("componentWillMount");
console.log("componentWillReceiveProps", props);
const [x, setX] = useState(0);
const [y, setY] = useState(0);
const [moveCount, setMoveCount] = useState(0);
const [cross, setCross] = useState(0);
const mouseMoveHandler = event => {
setX(event.clientX);
setY(event.clientY);
};
useEffect(() => {
console.log("componentDidMount");
document.addEventListener("mousemove", mouseMoveHandler);
return () => {
console.log("componentDidUnmount");
document.removeEventListener("mousemove", mouseMoveHandler);
};
}, []); // empty-array means don't watch for any updates
useEffect(
() => {
// if (componentDidUpdate & (x or y changed))
setMoveCount(moveCount + 1);
},
[x, y]
);
useEffect(() => {
// if componentDidUpdate
if (x === y) {
setCross(x);
}
});
return (
<div>
<p style={{ color: props.color }}>
Your mouse is at {x}, {y} position.
</p>
<p>Your mouse has moved {moveCount} times</p>
<p>
X and Y positions were last equal at {cross}, {cross}
</p>
</div>
);
};
作为第二个参数传递来触发x和y的更新,因为
在我的Medium出版物中也可以找到该文章。如果您喜欢炮兵,或者有任何意见和建议,请 拍手 ,或在{{3 }}。