網站首頁 編程語言 正文
react(含hooks)同步獲取state值
環境
"dependencies": {
? ? "babel-plugin-transform-decorators-legacy": "^1.3.5",
? ? "customize-cra": "^1.0.0",
? ? "rc-form": "^2.4.11",
? ? "react": "^17.0.1",
? ? "react-app-rewired": "^2.1.8",
? ? "react-dom": "^17.0.1",
? ? "react-router-dom": "^5.2.0",
? ? "react-scripts": "^4.0.1",
? ? "redux": "^4.0.5"
? },
代碼示例
hooks
import {useState} from "react";
export default function Pre04SetStateSync() {
? ? const [counter, setCounter] = useState(0)
? ? const add = () => {
? ? ? ? setCounter(counter + 1)
? ? ? ? console.log({counter})
? ? }
? ? return <>
? ? ? ? <h3>同步SetState</h3>
? ? ? ? <p>請觀察控制臺</p>
? ? ? ? <button onClick={add}>counter: {counter}</button>
? ? </>
}
class?
export default class Pre04SetStateSync extends React.Component{
? ? state = {
? ? ? ? counter:0
? ? }
? ? add = () => {
? ? ? ? this.setState({counter:this.state.counter + 1})
? ? ? ? console.log('~~this.state.counter',this.state.counter)
? ? }
? ? render() {
? ? ? ? return <>
? ? ? ? ? ? <h3>同步SetState</h3>
? ? ? ? ? ? <p>請觀察控制臺</p>
? ? ? ? ? ? <button onClick={this.add}>counter: {this.state.counter}</button>
? ? ? ? </>
? ? }
}
hooks結構中的setCounter(xxx)相當于class組件寫法中setState({counter: xxx})
可以對比控制臺看到,這樣直接setCounter(setState)后立即輸出的counter的是上一次的值,而按鈕上顯示正確,說明本次更新是異步的(react這樣設計是為了批量更新而提高性能),打印時counter還沒來得及改變。如果需要set完后立即取到counter的最新值,可以按如下方法實現同步的效果。
異步寫成同步的方法
1. 寫在setTimeout中
注意,只適用于class組件
add = () => {
? ? setTimeout(()=>{
? ? ? ? this.setState({counter:this.state.counter + 1})
? ? ? ? console.log('~~this.state.counter',this.state.counter)
? ? },0)
}
2. 合成事件使用原生事件替代
注意,只適用于class組件
// 原生事件
export default class Pre04SetStateSync extends React.Component {
? ? state = {
? ? ? ? counter: 0
? ? }
? ? componentDidMount() {
? ? ? ? document.querySelector('#btn').addEventListener('click', this.add)
? ? }
? ? add = () => {
? ? ? ? this.setState({counter: this.state.counter + 1})
? ? ? ? console.log('~~this.state.counter', this.state.counter)
? ? }
? ? render() {
? ? ? ? return <>
? ? ? ? ? ? <h3>同步SetState</h3>
? ? ? ? ? ? <p>請觀察控制臺</p>
? ? ? ? ? ? <button id='btn'>counter: {this.state.counter}</button>
? ? ? ? </>
? ? }
}
3. 寫入setState的回調函數中
注意,只適用于class組件
export default class Pre04SetStateSync extends React.Component {
? ? state = {
? ? ? ? counter: 0
? ? }
? ? add = () => {
? ? ? ? this.setState({counter: this.state.counter + 1}, ()=>{
? ? ? ? ? ? console.log('~~this.state.counter', this.state.counter)
? ? ? ? })
? ? }
? ? render() {
? ? ? ? return <>
? ? ? ? ? ? <h3>同步SetState</h3>
? ? ? ? ? ? <p>請觀察控制臺</p>
? ? ? ? ? ? <button onClick={this.add}>counter: {this.state.counter}</button>
? ? ? ? </>
? ? }
}
4. 連續setState的問題
注意,class組件和hooks都可以
如果將add改為先加1再加2,會發現代碼只執行了最后一個加2,加1被忽略了,如:
const add = () => {
? ? setCounter(counter + 1)
? ? setCounter(counter + 2)
}
解決方法是將setState的參數寫成函數形式
const add = () => {
? ? setCounter(counter => counter + 1)
? ? setCounter(counter => counter + 2)
}
5. 使用副作用useEffect
注意,只適用于hooks
export default function Pre04SetStateSync() {
? ? const [counter, setCounter] = useState(0)
? ? const add = () => {
? ? ? ? setCounter(counter + 1)
? ? }
? ? useEffect(() => {
? ? ? ? console.log({counter})
? ? }, [counter])
? ??
? ? return <>
? ? ? ? <h3>同步SetState</h3>
? ? ? ? <p>請觀察控制臺</p>
? ? ? ? <button onClick={add}>counter: {counter}</button>
? ? </>
}
react hooks常用方法
1.useState
function Example01(){
? ? const [ count, setCount ] = useState(0) ?//聲明
? ? return(
? ? ? ? <div>
? ? ? ? ? ? <p>{count}</p> ?//讀取
? ? ? ? ? ? <button onClick={()=>setCount(count+1)}>計數</button> // 使用(修改)
? ? ? ? </div>
? ? )
}
2.useEffect
1.React首次渲染和之后的每次渲染都會調用一遍useEffect函數,而之前我們要用兩個生命周期函數分別表示首次渲染(componentDidMonut)和更新導致的重新渲染(componentDidUpdate)
2.useEffect中定義的函數的執行不會阻礙瀏覽器更新視圖,也就是說這些函數時異步執行的,而componentDidMonut和componentDidUpdate中的代碼都是同步執行的。
注意:
如果useEffect后面沒有依賴:
這種時候每次每次頁面更新都會執行
useEffect(()=>{
? ? console.log('執行');
})
如果后面為空
頁面初始的時候執行一次
useEffect(()=>{
? ? console.log('執行');
},[])
如果后面有值且不為空
只有當count改變時才會被觸發
useEffect(()=>{
? ? console.log('執行');
},[count])
使用useEffect解綁,組件卸載的時候,比如需要清除計時器等:
但是當傳空數組[]時,就是當組件將被銷毀時才進行解綁,這也就實現了componentWillUnmount的生命周期函數。
function Index() {
? ? useEffect(()=>{
? ? ? ? console.log('useEffect=>Index')
? ? ? ? return ()=>{
? ? ? ? ? ? console.log('Index頁面離開')
? ? ? ? }
? ? },[])
? ? return <h2>測試解綁</h2>;
}
3.useContext上下文傳值
1.父組件:
const CountContext = createContext() ?//引入
function Example01(){
? ? const [ count, setCount ] = useState(0)
? ? return(
? ? ? ? <div>
? ? ? ? ? ? <p>{count}</p>
? ? ? ? ? ? <button onClick={()=>setCount(count+1)}>計數</button>
? ? ? ? ? ? <CountContext.Provider value={count}> ?//使用包裹子組件傳遞值
? ? ? ? ? ? ? ? <ChildContent/>
? ? ? ? ? ? </CountContext.Provider> ? ? ?
? ? ? ? </div>
? ? )
}
2.子組件:
function ChildContent(){
? ? ?const context = useContext(CountContext)?
? ? ?return(
? ? ? ? ?<p>{context}</p>
? ? ?)
}
4.useReducer
它也是React hooks提供的函數,可以增強我們的Reducer,實現類似Redux的功能。
import React, { useReducer ?} from 'react'
function Example5(){
? ? const [ count, dispatch ] = useReducer((state,action)=>{ ?
? ? ? ? ? ? ? switch(action){ ? //通過判斷對應的action,去執行對應的方法
? ? ? ? ? ? case 'add':
? ? ? ? ? ? ? ? return state+1
? ? ? ? ? ? case 'sub':
? ? ? ? ? ? ? ? return state-1
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? return state
? ? ? ? }
? ? },1)
? ? return(
? ? ? ? <div>
? ? ? ? ? ? <p>{count}</p>
? ? ? ? ? ? <button onClick={()=>dispatch('add')}>add</button> ?//通過dispatch,傳遞對應的action,調用對應的方法
? ? ? ? ? ? <button onClick={()=>dispatch('sub')}>sub</button>
? ? ? ? </div>
? ? )
}
export default Example5
5.useMemo
useMemo主要用來解決使用React hooks產生的無用渲染的性能問題。
只要使用useMemo,然后給她傳遞第二個參數,參數匹配成功,才會執行。
1.在父組件里面,傳遞對應需要的參數
import React , {useState,useMemo} from 'react';
function Example7(){
? ? const [one , setOne] = useState('第一個的狀態')
? ? const [two , setTwo] = useState('志玲待客狀態')
? ? return (
? ? ? ? <>
? ? ? ? ? ? <button onClick={()=>{setOne(new Date().getTime())}}>第一個</button>
? ? ? ? ? ? <button onClick={()=>{setTwo(new Date().getTime())}}>第二個</button>
? ? ? ? ? ? <ChildComponent name={one}>{two}</ChildComponent>
? ? ? ? </>
? ? )
}
2.父組件調用子組件
function ChildComponent({name,children}){
? ? function changeXiaohong(name){
? ? ? ? return name
? ? }
?const actionXiaohong = useMemo(()=>changeXiaohong(name),[name])
? ? return (
? ? ? ? <>
? ? ? ? ? ? <div>{actionXiaohong}</div>
? ? ? ? ? ? <div>{children}</div>
? ? ? ? </>
? ? )
}
6.useRef
用useRef獲取React JSX中的DOM元素,獲取后你就可以控制DOM的任何東西了。但是一般不建議這樣來作,React界面的變化可以通過狀態來控制
import React, { useRef } from 'react'
function Example8(){
? ? const inputRef ?= useRef(null)
? ? const onButtonClick=()=>{
? ? ? ? inputRef.current.value='THIS IS INPUT'
? ? ? ? console.log(inputRef);
? ? }
? ? return(
? ? ? ? <div>
? ? ? ? ? ? <input type="text" ref={inputRef}/>
? ? ? ? ? ? <button onClick = {onButtonClick}>顯示</button>
? ? ? ? </div>
? ? )
}
export default Example8
保存普通變量
import React, { useRef,useState } from 'react'
function Example8(){
? ? const inputRef ?= useRef(null)
? ? const onButtonClick=()=>{
? ? ? ? inputRef.current.value='THIS IS INPUT'
? ? ? ? console.log(inputRef);
? ? }
? ? ?const [state, setstate] = useState('inputValue') ?//聲明一個變量
? ? return(
? ? ? ? <div>
? ? ? ? ? ? <input type="text" ref={inputRef}/>
? ? ? ? ? ? <button onClick = {onButtonClick}>顯示</button>
? ? ? ? ? ? <input value={state} type="text" onChange={(e)=>setstate(e.target.value)}/> ?//綁定對應的值以及綁定onChange事件
? ? ? ? </div>
? ? )
}
export default Example8
原文鏈接:https://blog.csdn.net/daoke_li/article/details/112746505
相關推薦
- 2023-01-17 Python無權點文件轉化成鄰接矩陣方式_python
- 2023-07-04 ES聚合查詢+條件搜索的實現
- 2022-09-04 Python?numpy和matlab的幾點差異介紹_python
- 2023-06-19 Docker?查詢、停止、刪除和重啟容器的詳細過程_docker
- 2024-02-28 UNI-APP,實現給字符串中部分字符、子串添加樣式(顏色,字號等)
- 2022-08-15 SpringMVC異常處理流程總結
- 2022-04-03 django8.5?項目部署Nginx的操作步驟_nginx
- 2023-04-06 C++內存對齊的實現_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支