React Hooks - 使用 useState 与仅使用变量
Posted
技术标签:
【中文标题】React Hooks - 使用 useState 与仅使用变量【英文标题】:React Hooks - using useState vs just variables 【发布时间】:2020-02-03 17:45:23 【问题描述】:React Hooks 为我们提供了 useState 选项,我经常看到 Hooks 与 Class-State 的比较。但是 Hooks 和一些常规变量呢?
例如,
function Foo()
let a = 0;
a = 1;
return <div>a</div>;
我没有使用 Hooks,它会给我同样的结果:
function Foo()
const [a, setA] = useState(0);
if (a != 1) setA(1); // to avoid infinite-loop
return <div>a</div>;
那么有什么区别呢?在这种情况下使用 Hooks 更加复杂......那么为什么要开始使用它呢?
【问题讨论】:
您正在比较 2 个不同的事物。带有钩子的第二个函数具有更新数据的能力。第一个并没有真正做任何事情。你可以用let a = 1; return <div>a</div>
初始化它,你会得到同样的结果。
【参考方案1】:
原因是如果你useState
它会重新渲染视图。变量本身只会改变内存中的位,并且您的应用程序的状态可能与视图不同步。
比较这个例子:
function Foo()
const [a, setA] = useState(0);
return <div onClick=() => setA(a + 1)>a</div>;
function Foo()
let a = 0;
return <div onClick=() => a + 1>a</div>;
在这两种情况下,a
在点击时都会发生变化,但只有当您使用 useState
时,视图才能正确显示 a
的当前值。
【讨论】:
谢谢!因此,如果我不需要渲染视图 - 只是一种将我的数据(道具)组织到某个数组中的方法 - 我可以使用 'let' 吗?它对我有用,我只想知道它是否可以接受。 @MosheNagar 如果您从 props 派生数据,建议使用局部变量而不是保持数据处于状态,因为组件无论如何都会在 prop 更改时重新呈现,因此视图将与数据同步。将它们置于状态只会导致不必要的重新渲染 - 首先是道具更改,然后是状态更改。 另一种看待这个答案的方法是认为在第二种情况下,变量a
将在它完成执行后被垃圾收集,而在第一种情况下,因为它利用了@987654327 @它将保留a
的值
如果他不想重新渲染视图,他仍然可以使用useRef
。如果他应该使用局部变量或 React 引用,问题仍然存在。例如。如果您需要清除超时,或者使用 axios 进行持续的 http 请求,您是否将超时或 axios 源存储在变量或 React ref 中?
@Tom 一般规则是对派生状态使用本地变量。对于其他任何事情,请使用useRef
(如果您不想重新渲染)或useState
(如果您想重新渲染)。在计时器的情况下,由于它们是副作用,它们应该在useEffect
钩子中启动。如果您只想将timerId
用于清理目的,您可以将其保存在handler 的局部变量中。如果您希望能够从组件中的其他位置清除计时器,您应该使用useRef
。将timerId
存储在组件 的局部变量中是错误的,因为局部变量在每次渲染时都会“重置”。【参考方案2】:
您的第一个示例之所以有效,是因为数据基本上永远不会改变。使用setState
的切入点是在状态挂起时重新渲染整个组件。因此,如果您的示例需要某种状态更改或管理,您将很快意识到更改值是必要的,并且要使用变量值更新视图,您将需要状态和重新渲染。
【讨论】:
【参考方案3】:更新状态会使组件重新渲染,但局部值不会。
在您的情况下,您在组件中呈现了该值。 这意味着,当值更改时,组件应该重新渲染以显示更新后的值。
所以使用useState
会比正常的本地值更好。
function Foo()
let a = 0;
a = 1; // there will be no re-render.
return <div>a</div>;
function Foo()
const [a, setA] = useState(0);
if (a != 1) setA(1); // re-render required
return <div>a</div>;
【讨论】:
【参考方案4】:function Foo()
const [a, setA] = useState(0);
if (a != 1) setA(1); // to avoid infinite-loop
return <div>a</div>;
等价于
class Foo extends React.Component
constructor(props)
super(props);
this.state =
a: 0
;
// ...
useState
返回的是两件事:
-
新的状态变量
该变量的设置器
如果您调用setA(1)
,您将调用this.setState( a: 1 )
并触发重新渲染。
【讨论】:
【参考方案5】:局部变量将在每次渲染时重置,而状态将更新:
function App()
let a = 0; // reset to 0 on render/re-render
const [b, setB] = useState(0);
return (
<div className="App">
<div>
a
<button onClick=() => a++>local variable a++</button>
</div>
<div>
b
<button onClick=() => setB(prevB => prevB + 1)>
state variable b++
</button>
</div>
</div>
);
【讨论】:
Local variables will get reset every render upon mutation whereas state will update
。功能组件是正确的。类组件呢?
@NguyễnVănPhong 如果您指的是类属性,不,它们存在于组件生命周期之外。如果您指的是在 render
生命周期方法中声明的任何变量(例如),这些变量将在每次渲染时重新声明,就像在功能组件中一样。
这是有道理的。 +1以上是关于React Hooks - 使用 useState 与仅使用变量的主要内容,如果未能解决你的问题,请参考以下文章
React Hooks --- useState 和 useEffect
React Hooks:使用useState更新状态不会立即更新状态[重复]
使用 useState 和 useContext React Hooks 持久化 localStorage