react钩子_usestate钩子的几种状态在React

react钩子

Hooks have changed the way we write React components. It encourages a much more functional and composable style of coding that was difficult to achieve with class components. One of the biggest game-changers is the useState hook.

挂钩改变了我们编写React组件的方式。 它鼓励使用类组件很难实现的更具功能性和可组合性的编码样式。 最大的改变游戏规则之一是useState挂钩。

Before hooks, React state was managed by a single state property on the class component. This property had to be an object and had to be updated with a class method called this.setState which despite its name, didn’t set the state, it patched the state with whichever object we provided it. Though this worked well, it encouraged us to throw all the state in this one object, even though the value were not related or updated together. It wouldn’t be uncommon to have a state object look like this:

在进行钩子之前,React状态由类组件上的单个state属性管理。 该属性必须是一个对象,并且必须使用名为this.setState的类方法进行更新,尽管该类方法this.setState其名称,但并未设置状态,而是使用我们提供的任何对象来修补该状态。 尽管此方法运行良好,但它鼓励我们将所有状态都放在该对象中,即使值没有关联或一起更新。 使状态对象看起来像这样并不罕见:

{
toolTipIsVisible:false,
userList:[...],
formData:{...},
matchesMedia:false,
inViewPort:true,
....
}

All this state was data that need to be saved and maintained, but they didn’t need to be maintained together nor live in the same object, other than this was the limitation of the class component. This also made refactoring difficult, because it wasn’t always obvious which parts of the state needed to stay together and could be lifted into a parent component or dropped into a child component.

所有这些状态都是需要保存和维护的数据,但是它们不需要一起维护或驻留在同一对象中,除了这是类组件的局限性。 这也使重构变得困难,因为并不总是很明显需要将状态的哪些部分放在一起,并且可以将其提升到父组件中或放到子组件中。

In an attempt to clean some of this up, Higher-Order Components and Render Prop patterns emerged. Though this did allow the state and functions that maintained them to be grouped, it was still just a hack and we needed a proper primitive to handle this better. This is where Hooks come in.

为了清理其中的某些内容,出现了高阶组件和渲染道具模式。 尽管这确实允许将维护它们的状态和功能进行分组,但这仍然只是一个hack,我们需要一个适当的原语来更好地处理此问题。 这是钩子进来的地方。

基本用例 (Basic Use Cases)

The useState hook is very simple. You can either invoke it on the React object directly or destructure it from the import like this:

useState挂钩非常简单。 您可以直接在React对象上调用它,也可以从导入中对其进行解构,如下所示:

import React, {useState} from 'react'

The useState hook simply takes an initial value and will return an array with two values in it. The first value is the current value and the second value is the method you need to update the value. Here is an example:

useState挂钩仅使用一个初始值,并将返回一个包含两个值的数组。 第一个值是当前值,第二个值是更新值所需的方法。 这是一个例子:

const stateArray = useState(/* initial value */);const value = stateArray[0];
const setValue = stateArray[1];

Luckily, using array destructuring, this can be simplified to one line like this:

幸运的是,使用数组解构可以将其简化为以下一行:

const [value, setValue] = useState(/* initial value */);

So now we can rewrite our component state like this:

现在,我们可以像这样重写组件状态:

const [toolTipIsVisible, set toolTipIsVisible] = useState(false)const [userList, setUserList] = useState([...])const [formData, setFormData] = useState({...})const [matchesMedia, setMatchesMedia] = useState(false)const [inViewPort, setViewPort] = useState(false)}

(From the above, you will notice a convention that has evolved naturally since hooks were first introduced. That pattern is not required but is typical in many codebases now. It is const [<name>, set<Name>] = useState(). )

(从上面可以看到,自从首次引入钩子以来,约定就自然地发展了。该模式不是必需的,但现在在许多代码库中都是典型的。它是const [<name>, set<Name>] = useState(). )

One might ask how this is better, in some ways you now have to keep track of more methods to update the individual states. But the nice benefit this gives us is flexibility. For example, the matchesMedia and inViewPort probably could be refactored into their hook, depending on how your components are built, you may be able to move the userList and formData down into a child component. We can refactor it to be something like this:

有人可能会问这有什么好处,现在您必须以某种方式跟踪更多的方法来更新各个状态。 但这给我们带来的好处是灵活性。 例如, matchesMediainViewPort可能可以重构到其挂钩中,具体取决于您的组件的构建方式,您可以将userListformData向下移动到子组件中。 我们可以将其重构为如下形式:

const Form = ()=>{
const [formData, setFormData] = useState({...})
...
}const Users = ()=>{
const [userList, setUserList] = useState([...])
...
}const App = ()=>{
const [toolTipIsVisible, set toolTipIsVisible] = useState(false)
const matchesMedia = useMatchMedia(...)
const inViewPort = useIntersection(...)

/* render the Form and Users and everything else */
}

When each state is managed separately, it’s as simple as cut & paste and you have done most of the refactoring right there.

分别管理每个状态时,就像剪切和粘贴一样简单,您就可以在那里完成大部分重构。

从先前状态派生状态 (Deriving State From the Previous State)

The setState function that is returned from useState can be used in two ways. The easiest and simplest way is to just pass the new value into it, like so:

useState返回的setState函数可以两种方式使用。 最简单最简单的方法是将新值传递给它,如下所示:

const [isVisible, setIsVisible] = useState(true)...<button onClick={()=>setIsVisible(false)}>Close</button>

This function, however, can also accept a function. This function takes the previous state as an argument and then whatever is returned from the function will be set as the new state. Like this:

但是,此功能也可以接受功能。 该函数将先前的状态作为参数,然后将从该函数返回的任何内容设置为新状态。 像这样:

const [isVisible, setIsVisible] = useState(true)...<button onClick={()=>setIsVisible(prevState => !prevState)}>
Toggle SideBar
</button>

One might ask, why would you need to do this? Couldn’t you just as simply derive the state from the current value like this:

有人可能会问,您为什么需要这样做? 您不能像这样从当前值简单地得出状态:

setIsVisible(!isVisible)

There is one big reason that this can be problematic: concurrency. When React renders, it has to live in a world where asynchronous processes are the norm. The setState function return from the useState hook is asynchronous already and then if you add on top of that the code you write that calls the function is quite possibly asynchronous as well you have no way to guarantee what has happened to the state while you wait for the code to update. This means that the value of your state can become stale by the time your function runs.

造成问题的一个主要原因是:并发。 当React渲染时,它必须生活在一个以异步流程为标准的世界中。 从useState挂钩返回的setState函数已经是异步的,然后,如果在此之上加上调用该函数编写的代码,则很可能也是异步的,因此您无法保证在等待时状态发生了什么变化要更新的代码。 这意味着在函数运行时状态值可能会过时。

You could write code like the example above without using a function and never have a bug, but I would highly recommend that if the new state is derived from the previous state, that you use the function pattern to ensure that your updates are consistent

您可以像上面的示例一样编写代码而无需使用函数,并且永远不会有错误,但是我强烈建议,如果新状态是从先前状态派生的,则应使用函数模式来确保更新是一致的

对象也可以处于状态(Objects Can Be State Too)

The useState hook has removed the requirement to keep the state in a single object, but that doesn’t mean we stop using objects as state values. Some values need to be group together, which is why we have objects in the language in the first place.

useState钩子删除了将状态保持在单个对象中的要求,但这并不意味着我们停止将对象用作状态值。 一些值需要组合在一起,这就是为什么我们首先使用该语言的对象。

The confusion arises when we have values that need to be grouped but updated independently, like form state for example. It might be tempting to break up the object into separate useState hooks to make updating the values easier, but this is problematic for two reasons. First is that we lose the benefit and semantics of having an object. Secondly, we can already update individual values with the current setState functions. All we have to do is take advantage of the spread operator like this:

当我们具有需要分组但需要独立更新的值(例如表单状态)时,就会产生混乱。 可能useState将对象分成单独的useState挂钩以使更新值更容易,但这有两个问题。 首先,我们失去了拥有对象的好处和语义。 其次,我们已经可以使用当前的setState函数更新各个值。 我们要做的就是利用这样的传播算子:

setFormData(prevForm => ({...prevForm, userName:"newUserName"}))

Spreading object values into a new object has been around since 2015 and allows you to do a shallow copy of all the values of one object into a new object. We can then take advantage of how JavaScript Objects works, namely that you cannot have duplicate keys and if you set the key more than once, the last one wins. Just like above, since we are deriving that state from a previous state, we will use the function syntax.

自2015年以来一直在将对象值传播到一个新对象中,使您可以将一个对象的所有值复制到一个新对象中。 然后,我们可以利用JavaScript对象的工作原理,即您不能拥有重复的键,并且如果您多次设置键,则最后一个键会获胜。 就像上面一样,由于我们要从先前的状态派生该状态,因此我们将使用函数语法。

The useState hook, though simple, is a very versatile hook. By using it to its full potential, you can do many, if not all the state management needs your app needs.

useState钩子虽然简单,但却是一种非常通用的钩子。 通过充分利用它,您可以完成许多(即使不是全部)状态管理需要您的应用程序需求的工作。

翻译自: https://medium.com/the-non-traditional-developer/the-several-states-of-the-usestate-hook-in-react-113b346cb63c

react钩子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值