React Hook:useState
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
但是不要什么业务都使用hook,请在合适的时候使用hook,否则会造成性能问题.(能不用的时候就不能,当遇到性能不好优化的时候,自然会想到使用它)
useState
//语法: 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来实现相同的效果.