React Hook:useState

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

但是不要什么业务都使用hook,请在合适的时候使用hook,否则会造成性能问题.(能不用的时候就不能,当遇到性能不好优化的时候,自然会想到使用它)

 

useState

1.useState和类组件的this.state一样,都是用来管理组件状态的。在React Hook没出来之前,函数组件也叫做Functional Stateless Component(FSC:功能无状态的组件),这是因为函数组件每次执行的时候都会生成新的函数作用域所以同一个组件的不同渲染(render)之间是不能够共用状态的,因此开发者一旦需要在组件中引入状态就需要将原来的函数组件改成类组件,这使得开发者的体验十分不好(面试:具体哪些不友好?)。

useState就是用来解决这个问题的,它允许函数组件将自己的状态持久化到React运行时的某个地方,这样在组件每次重新渲染的时候都可以从这个地方拿到该状态,而且当该状态被更新的时候,组件也会重渲染。

语法:

//语法:
import React,{useState} from "react"

const [state, setState] = useState(initialState)//数组解构赋值

//useState接收一个initialState变量作为状态的初始值,返回值是一个数组。返回数组的第一个元素代表当前state的最新值,第二个元素是一个用来更新state的函数。state和setState这两个变量的命名是你自己取的
//state用于组件内部使用的数据
//setState函数用于修改state,当修改后会触发所有使用过state的地方重新取值(调用render)
//可以用多个useState

 

例1:

React 特性

import React, { useState } from 'react';

function Example() {
  
// 声明一个新的叫做 “count” 的 state 变量 const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
export default Example;

 

例2:

import React, { useState } from 'react'
import ReactDOM from 'react-dom'

const App = () => {
//{count,setcount} const [counter, setCounter]
= useState(0) const [text, setText] = useState('') const change1 = (event) => { setText(event.target.value) }
//数组的0下标的值就是有状态的数据 传入的参数就是0下标的初始数据 //下标是一个函数,调用这个函数跨域修改0下标的数据 而且刷新页面中使用过0下标的模板
return ( <div> <div>{counter}</div> <button onClick={() => setCounter(counter + 1)} >+</button>
//直接写setcount()会死循环,要加一个箭头函数 <input onChange={change1} value={text}/> <div/> ) } ReactDOM.render(<App />, document.getElementById('root'))

 

注意

React 16.8.0 是第一个支持 Hook 的版本。升级时,请注意更新所有的 package,包括 React DOM。 React Native 从 0.59 版本开始支持 Hook。

 

Hook 是:

  • 完全可选的。 你无需重写任何已有代码就可以在一些组件中尝试 Hook。但是如果你不想,你不必现在就去学习或使用 Hook。
  • 100% 向后兼容的。 Hook 不包含任何破坏性改动。
  • 现在可用。 Hook 已发布于 v16.8.0。

没有计划从 React 中移除 class。

Hook 不会影响你对 React 概念的理解。 恰恰相反,Hook 为已知的 React 概念提供了更直接的 API:props, state,context,refs 以及生命周期。

 

2.useState的initialState也可以是一个用来生成状态初始值的函数,这种做法主要是避免组件每次渲染的时候initialState需要被重复计算

const [state, setState] = useState(() => {
  const initialState = localstorge.getItem("isLogin")
  return initialState
})

 

 

3.setState[1] 的调用修改是全量替代(面试)

函数组件的setState和类组件的this.setState函数的一个重要区别是:

类组件是将当前设置的state浅归并到旧state的操作。而hook的setState函数则是将新state直接替换旧的state。因此我们在编写函数组件的时候,就要合理划分state,避免将没有关系的状态放在一起管理.

案例:

//不好的设计:
const [state, setState] = useState({ left: 0, top: 0, width: 0, height: 0 })
​
//由于我们将互不关联的DOM位置信息{left: 0, top: 0}和大小信息{width: 0, height: 0}绑定在同一个state,所以我们在更新任意一个状态的时候也要维护一下另外一个状态:
const handleContainerResize = ({ width, height }) => {
  setState({...state, width, height})
}
​
const handleContainerMove = ({ left, top }) => {
  setState({...state, left, top})
}
​
​
​
​
//正确的设计:
const [position, setPosition] = useState({ left: 0, top: 0 })
const [size, setSize] = useState({ width: 0, height: 0})
​
const handleContainerResize = ({ width, height }) => {
  setSize({width, height})
}
​
const handleContainerMove = ({ left, top }) => {
  setPosition({left, top})
}
​
//ps:如果你非要将多个互不关联的状态放在一起的话,可以使用useReducer来管理状态,这样你的代码会更好维护。
 

 

4.setState没有回调函数(面试)

无论是useState还是类组件的this.setState都是异步调用的,也就是说每次组件调用完之后都不能立即拿到最新的state值。

为了解决这个问题,类组件的this.setState允许通过一个回调函数来获取到最新的state值:

this.setState(newState, state => { console.log( state)})

函数组件的setState函数不存在这么一个可以拿到最新state的回调函数,不过我们可以使用useEffect来实现相同的效果.

 
posted on 2022-10-19 10:09  香香鲲  阅读(74)  评论(0编辑  收藏  举报