useState 和 useEffect 有什么区别?
What’s the difference between useState and useEffect?
我在react v16中看到了这两个新概念
据我了解:
useState
is similar like setState
with hooks and useEffect
works similarly like life cycle methods.
我的理解对吗?如果不是,useState
和 useEffect
之间的确切区别是什么?
对于useState()
首先,我们有功能组件不支持state
,换句话说,功能组件是无状态组件.
现在,有了 Hooks,我们有了 功能组件 但 有状态 。它是通过使用 useState.
来实现的
对于useEffect()
首先,对于无状态功能组件,我们没有组件生命周期挂钩。换句话说,每当你想使用组件生命周期钩子时,你应该考虑使用class组件.
现在,我们可以在不使用class组件的情况下使用组件生命周期钩子。它是通过使用 useEffect 来实现的。换句话说,现在每当我们想使用 component lifecycle hooks 时,我们已经有两个选择,要么使用 class component 要么使用 Hooks useEffect
.
更新
what’s the exact difference between useState
and useEffect
?
简单来说,useState
允许我们的 功能组件 曾经是 无状态的 变成 有状态的。 useEffect
允许我们的 功能组件 利用 组件生命周期挂钩 ,在过去,只有 支持class 个组件.
简单来说,useState
和 useEffect
都增强了功能组件,使它们可以做 classes 可以但功能组件(没有钩子)不能的事情:
useState
允许功能组件具有 状态 ,就像 class 组件中的 this.state
。
useEffect
允许功能组件将 生命周期方法 (例如 componentDidMount
、componentDidUpdate
和 componentWillUnmount
)合二为一单身 API.
请参阅以下示例以进一步说明:
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>
useState
和 useEffect
是 React 16.8+ hooks 生态系统的一部分,旨在为功能组件提供相同的功能,而这些功能以前只有基于 class 的组件才可用(state
/ setState
和组件生命周期方法(例如 componentDidMount
、componentDidUpdate
和 componentWillUnmount
)
useState()
是直截了当的,它让你在功能组件中拥有状态访问器。
useEffect()
可以组合 componentDidMount
、componentDidUpdate
和 componentWillUnmount
,但很棘手。
你可以从 hooks 的官方文档中解读我在这里要讨论的大部分内容。在工作中看到钩子比从文本推理更容易。
预渲染生命周期
预渲染生命周期 事件相当于 componentWillReceiveProps
或 getDerivedStateFromProps
和 componentWillMount
可以只是我们在功能中首先做的事情returning JSX(react-node)之前的组件作为函数本身等同于 render(…)
基于 class 的组件的方法。
我们不需要钩子来处理预渲染生命周期事件。
Post-渲染生命周期
Post-渲染生命周期事件,相当于[=117=中的componentDidMount
、componentDidUpdate
和componentDidUnmount
] 基于组件。
我们需要 ****_useEffect(…)_**
来处理这些Post-render生命周期事件** 因为我们不能在主组件函数中编写与这些生命周期事件相关的逻辑,因为这些应该在组件函数returns JSX(反应节点)之后运行 ) 到 react-dom
渲染器。
这意味着,我们可以用钩子做很多事情。怎么样?
我们知道 useEffect(fn, […watchStates])
,接受 2 个参数。
fn
:(必需)useEffect
将此函数调用到 运行 作为每个渲染周期后的副作用,基于跟踪 (2) 参数给出的更改的值.函数 fn
,可以 return 另一个应该 运行 的函数,作为效果函数 运行 再次或组件卸载前的清理
[…watchValues ]
:(可选)useEffect
跟踪此数组中的值自上次渲染周期以来已更改,然后仅调用效果 fn
。如果未给出此参数,效果将 运行 每个渲染周期。
如果我们不一起传递 (2) 参数,fn
中的效果逻辑将在每个渲染周期后调用。
如果我们传递 (2) 带有值的数组,组件需要观察变化,并在变化时调用 fn
,非常不言自明。
最棘手的部分是使用空数组 []
作为 (2) 参数,我们可以限制 fn
中的副作用逻辑仅在安装阶段执行,因为没有更改效果挂钩将在后续渲染周期后再次触发 fn
。
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>
);
};
代码片段简单明了。您可以在 CodePen.
上试用
需要注意的一件重要事情是,如果您在效果内部进行状态更改,请确保从监视数组中排除正在更改的状态。
例如,在第二个效果(计算鼠标移动的效果)中,我们只在 x 和 y 更新时触发它,通过将 [x , y]
作为第二个参数传递,因为
- 观察 x 和 y 的变化以记录鼠标移动在逻辑上是正确的
- 如果我们不排除 moveCount 被监视,这个 useEffect 将进入无限循环,因为我们将更新同样的值,我们也在监视变化
这篇文章也可以在我的 Medium publication. If you like the artile, or have any comments and suggestions, please clap or leave comments on Medium.
上找到
我在react v16中看到了这两个新概念
据我了解:
useState
is similar likesetState
with hooks anduseEffect
works similarly like life cycle methods.
我的理解对吗?如果不是,useState
和 useEffect
之间的确切区别是什么?
对于useState()
首先,我们有功能组件不支持state
,换句话说,功能组件是无状态组件.
现在,有了 Hooks,我们有了 功能组件 但 有状态 。它是通过使用 useState.
来实现的对于useEffect()
首先,对于无状态功能组件,我们没有组件生命周期挂钩。换句话说,每当你想使用组件生命周期钩子时,你应该考虑使用class组件.
现在,我们可以在不使用class组件的情况下使用组件生命周期钩子。它是通过使用 useEffect 来实现的。换句话说,现在每当我们想使用 component lifecycle hooks 时,我们已经有两个选择,要么使用 class component 要么使用 Hooks useEffect
.
更新
what’s the exact difference between
useState
anduseEffect
?
简单来说,useState
允许我们的 功能组件 曾经是 无状态的 变成 有状态的。 useEffect
允许我们的 功能组件 利用 组件生命周期挂钩 ,在过去,只有 支持class 个组件.
简单来说,useState
和 useEffect
都增强了功能组件,使它们可以做 classes 可以但功能组件(没有钩子)不能的事情:
useState
允许功能组件具有 状态 ,就像 class 组件中的this.state
。useEffect
允许功能组件将 生命周期方法 (例如componentDidMount
、componentDidUpdate
和componentWillUnmount
)合二为一单身 API.
请参阅以下示例以进一步说明:
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>
useState
和 useEffect
是 React 16.8+ hooks 生态系统的一部分,旨在为功能组件提供相同的功能,而这些功能以前只有基于 class 的组件才可用(state
/ setState
和组件生命周期方法(例如 componentDidMount
、componentDidUpdate
和 componentWillUnmount
)
useState()
是直截了当的,它让你在功能组件中拥有状态访问器。
useEffect()
可以组合 componentDidMount
、componentDidUpdate
和 componentWillUnmount
,但很棘手。
你可以从 hooks 的官方文档中解读我在这里要讨论的大部分内容。在工作中看到钩子比从文本推理更容易。
预渲染生命周期
预渲染生命周期 事件相当于 componentWillReceiveProps
或 getDerivedStateFromProps
和 componentWillMount
可以只是我们在功能中首先做的事情returning JSX(react-node)之前的组件作为函数本身等同于 render(…)
基于 class 的组件的方法。
我们不需要钩子来处理预渲染生命周期事件。
Post-渲染生命周期
Post-渲染生命周期事件,相当于[=117=中的componentDidMount
、componentDidUpdate
和componentDidUnmount
] 基于组件。
我们需要 ****_useEffect(…)_**
来处理这些Post-render生命周期事件** 因为我们不能在主组件函数中编写与这些生命周期事件相关的逻辑,因为这些应该在组件函数returns JSX(反应节点)之后运行 ) 到 react-dom
渲染器。
这意味着,我们可以用钩子做很多事情。怎么样?
我们知道 useEffect(fn, […watchStates])
,接受 2 个参数。
fn
:(必需)useEffect
将此函数调用到 运行 作为每个渲染周期后的副作用,基于跟踪 (2) 参数给出的更改的值.函数fn
,可以 return 另一个应该 运行 的函数,作为效果函数 运行 再次或组件卸载前的清理[…watchValues ]
:(可选)useEffect
跟踪此数组中的值自上次渲染周期以来已更改,然后仅调用效果fn
。如果未给出此参数,效果将 运行 每个渲染周期。
如果我们不一起传递 (2) 参数,fn
中的效果逻辑将在每个渲染周期后调用。
如果我们传递 (2) 带有值的数组,组件需要观察变化,并在变化时调用 fn
,非常不言自明。
最棘手的部分是使用空数组 []
作为 (2) 参数,我们可以限制 fn
中的副作用逻辑仅在安装阶段执行,因为没有更改效果挂钩将在后续渲染周期后再次触发 fn
。
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>
);
};
代码片段简单明了。您可以在 CodePen.
上试用需要注意的一件重要事情是,如果您在效果内部进行状态更改,请确保从监视数组中排除正在更改的状态。
例如,在第二个效果(计算鼠标移动的效果)中,我们只在 x 和 y 更新时触发它,通过将 [x , y]
作为第二个参数传递,因为
- 观察 x 和 y 的变化以记录鼠标移动在逻辑上是正确的
- 如果我们不排除 moveCount 被监视,这个 useEffect 将进入无限循环,因为我们将更新同样的值,我们也在监视变化
这篇文章也可以在我的 Medium publication. If you like the artile, or have any comments and suggestions, please clap or leave comments on Medium.
上找到