中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

明星用什么軟件做視頻網(wǎng)站友情鏈接方面

明星用什么軟件做視頻網(wǎng)站,友情鏈接方面,網(wǎng)上訂餐網(wǎng)站模板,網(wǎng)站備案 英文useReducer usereducer 相當(dāng)于 復(fù)雜的 useState 當(dāng)狀態(tài)更新邏輯較復(fù)雜時(shí)可以考慮使用 useReducer。useReducer 可以同時(shí)更新多個(gè)狀態(tài),而且能把對(duì)狀態(tài)的修改從組件中獨(dú)立出來。 相比于 useState,useReducer 可以更好的描述“如何更新狀態(tài)”。例如&#…

useReducer

usereducer 相當(dāng)于 復(fù)雜的 useState
當(dāng)狀態(tài)更新邏輯較復(fù)雜時(shí)可以考慮使用 useReducer。useReducer 可以同時(shí)更新多個(gè)狀態(tài),而且能把對(duì)狀態(tài)的修改從組件中獨(dú)立出來。

相比于 useState,useReducer 可以更好的描述“如何更新狀態(tài)”。例如:組件負(fù)責(zé)發(fā)出行為,useReducer 負(fù)責(zé)更新狀態(tài)。

好處是:讓代碼邏輯更清晰,代碼行為更易預(yù)測(cè)。

1. useReducer 的語(yǔ)法格式

useReducer 的基礎(chǔ)語(yǔ)法如下:

const [state, dispatch] = useReducer(reducer, initState, initAction?)

其中:

1. reducer 是一個(gè)函數(shù),類似于 (prevState, action) => newState。形參 prevState 表示舊狀態(tài),形參 action 表示本次的行為,返回值 newState 表示處理完畢后的新狀態(tài)。

2. initState 表示初始狀態(tài),也就是默認(rèn)值。

3. initAction 是進(jìn)行狀態(tài)初始化時(shí)候的處理函數(shù),它是可選的,如果提供了 initAction 函數(shù),則會(huì)把 initState 傳遞給 initAction 函數(shù)進(jìn)行處理,initAction 的返回值會(huì)被當(dāng)做初始狀態(tài)。

4. 返回值 state 是狀態(tài)值。dispatch 是更新 state 的方法,讓他接收 action 作為參數(shù),useReducer 只需要調(diào)用 dispatch(action) 方法傳入的 action 即可更新 state。

2. 定義組件的基礎(chǔ)結(jié)構(gòu)

定義名為 Father 的父組件如下:

import React from 'react'// 父組件
export const Father: React.FC = () => {return (<div><button>修改 name 的值</button><div className="father"><Son1 /><Son2 /></div></div>)
}

定義名為 Son1 和 Son2 的兩個(gè)子組件如下:

// 子組件1
const Son1: React.FC = () => {return <div className="son1"></div>
}// 子組件2
const Son2: React.FC = () => {return <div className="son2"></div>
}

在 index.css 中添加對(duì)應(yīng)的樣式:

.father {display: flex;justify-content: space-between;width: 100vw;
}.son1 {background-color: orange;min-height: 300px;flex: 1;padding: 10px;
}.son2 {background-color: lightblue;min-height: 300px;flex: 1;padding: 10px;
}

3. 定義 useReducer 的基礎(chǔ)結(jié)構(gòu)

1、按需導(dǎo)入 useReducer 函數(shù):

import React, { useReducer } from 'react'

2、定義初始數(shù)據(jù)

const defaultState = { name: 'liulongbin', age: 16 }

3、定義 reducer 函數(shù),它的作用是:根據(jù)舊狀態(tài),進(jìn)行一系列處理,最終返回新狀態(tài)

// 第一個(gè)參數(shù)永遠(yuǎn)是上一次的舊狀態(tài)
const reducer = (prevState) => {// 首次進(jìn)入頁(yè)面 不會(huì)觸發(fā) reducer 函數(shù)執(zhí)行console.log('觸發(fā)了 reducer 函數(shù)')// 必須向外返回一個(gè)處理好的新狀態(tài) return prevState
}

4、在 Father 組件中,調(diào)用 useReducer(reducerFn, 初始狀態(tài)) 函數(shù),并得到 reducer 返回的狀態(tài):

// 父組件
export const Father: React.FC = () => {// useReducer(fn, 初始數(shù)據(jù), 對(duì)初始數(shù)據(jù)進(jìn)行處理的fn)const [state] = useReducer(reducer, defaultState)console.log(state)return (<div><button>修改 name 的值</button><div className="father"><Son1 /><Son2 /></div></div>)
}

5、為 reducer 中的 initState 指定數(shù)據(jù)類型:

// 定義狀態(tài)的數(shù)據(jù)類型
type UserType = typeof defaultStateconst defaultState = { name: 'liulongbin', age: 16 }// 給 initState 指定類型為 UserType
const reducer = (prevState: UserType) => {console.log('觸發(fā)了 reducer 函數(shù)')return prevState
}

6、接下來,在 Father 組件中使用 state 時(shí),就可以出現(xiàn)類型的智能提示啦:

// 父組件
export const Father: React.FC = () => {const [state] = useReducer(reducer, defaultState)console.log(state.name, state.age)return (<div><button>修改 name 的值</button><div className="father"><Son1 /><Son2 /></div></div>)
}

4. 使用 initAction 處理初始數(shù)據(jù)

定義名為 initAction 的處理函數(shù),如果初始數(shù)據(jù)中的 age 為小數(shù)、負(fù)數(shù)、或 0 時(shí),對(duì) age 進(jìn)行非法值的處理:

const initAction = (initState: UserType) => {// 把 return 的對(duì)象,作為 useReducer 的初始值return { ...initState, age: Math.round(Math.abs(initState.age)) || 18 }
}

Father 組件中,使用步驟1聲明的 initAction 函數(shù)如下:

// 父組件
export const Father: React.FC = () => {// useReducer(fn, 初始數(shù)據(jù), 對(duì)初始數(shù)據(jù)進(jìn)行處理的fn)const [state] = useReducer(reducer, defaultState, initAction)// 省略其它代碼...
}

在定義 defaultState 時(shí),為 age 提供非法值,可以看到非法值在 initAction 中被處理掉了。

5. 在 Father 組件中點(diǎn)擊按鈕修改 name 的值

1. 錯(cuò)誤示范:

不要像 vue 響應(yīng)式數(shù)據(jù)一樣,直接通過 state.name = 'escook' 去修改

// 父組件
export const Father: React.FC = () => {// useReducer(fn, 初始數(shù)據(jù), 對(duì)初始數(shù)據(jù)進(jìn)行處理的fn)const [state] = useReducer(reducer, defaultState, initAction)console.log(state)const onChangeName = () => {// 注意:這種用法是錯(cuò)誤的,因?yàn)椴荒堋局苯有薷?state 的值】// 因?yàn)榇鎯?chǔ)在 useReducer 中的數(shù)據(jù)都是“不可變”的!// 要想修改 useReducer 中的數(shù)據(jù),必須觸發(fā) 【reducer】 函數(shù)的重新計(jì)算,// 根據(jù) reducer 形參中的舊狀態(tài)對(duì)象(initState),經(jīng)過一系列處理,返回一個(gè)“全新的”狀態(tài)對(duì)象state.name = 'escook'}return (<div><button onClick={onChangeName}>修改 name 的值</button><div className="father"><Son1 /><Son2 /></div></div>)
}

2. 正確的操作

為了能夠觸發(fā) reducer 函數(shù)的重新執(zhí)行,我們需要在調(diào)用 useReducer() 后接收返回的 dispatch 函數(shù)。示例代碼如下:

// Father 父組件 
const [state, dispatch] = useReducer(reducer, defaultState, initAction)

在 button 按鈕的點(diǎn)擊事件處理函數(shù)中,調(diào)用 dispatch() 函數(shù),從而觸發(fā) reducer 函數(shù)的重新計(jì)算:

// Father 父組件 
const onChangeName = () => { dispatch() 
}

點(diǎn)擊 Father 組件中如下的 button 按鈕:

<button onClick={onChangeName}>修改 name 的值</button>

會(huì)觸發(fā) reducer 函數(shù)的重新執(zhí)行,并打印 reducer 中的 console.log(),代碼如下:

const reducer = (prevState: UserType) => {console.log('觸發(fā)了 reducer 函數(shù)')return prevState
}

3. 調(diào)用 dispatch 傳遞參數(shù)給 reducer

在 Father 父組件按鈕的點(diǎn)擊事件處理函數(shù) onChangeName 中,調(diào)用 dispatch() 函數(shù)并把參數(shù)傳遞給 reducer 的第2個(gè)形參,代碼如下:

const onChangeName = () => {// 注意:參數(shù)的格式為 { type, payload? }// 其中:// type 的值是一個(gè)唯一的標(biāo)識(shí)符,用來【指定本次操作的類型】,一般為大寫的字符串// payload 是本次操作需要用到的數(shù)據(jù),為可選參數(shù)。在這里,payload 指的是把用戶名改為字符串 '劉龍彬'dispatch({type: 'UPDATE_NAME', payload: '劉龍彬'})
}

修改 reducer 函數(shù)的形參,添加名為 action 的第2個(gè)形參,用來接收 dispatch 傳遞過來的數(shù)據(jù)

const reducer = (prevState: UserType, action) => {// 打印 action 的值,終端顯示的值為:// {type: 'UPDATE_NAME', payload: '劉龍彬'}console.log('觸發(fā)了 reducer 函數(shù)', action)return prevState
}

在 reducer 中,根據(jù)接收到的 action.type 標(biāo)識(shí)符,決定進(jìn)行怎樣的更新操作,最終 return 一個(gè)計(jì)算好的新狀態(tài)。示例代碼如下:

const reducer = (prevState: UserType, action) => {console.log('觸發(fā)了 reducer 函數(shù)', action)// return prevStateswitch (action.type) {// 如果標(biāo)識(shí)符是字符串 'UPDATE_NAME',則把用戶名更新成 action.payload 的值// 最后,一定要返回一個(gè)新狀態(tài),因?yàn)?useReducer 中每一次的狀態(tài)都是“不可變的”case 'UPDATE_NAME':return { ...prevState, name: action.payload }   // 解除引用,賦予新對(duì)象// 兜底操作:// 如果沒有匹配到任何操作,則默認(rèn)返回上一次的舊狀態(tài)default:return prevState}
}

4、為 action 指定類型

在上述的 switch...case... 代碼期間,沒有 TS 的類型提示,這在大型項(xiàng)目中是致命的。因此,我們需要為 reducer 函數(shù)的第2個(gè)形參 action 指定操作的類型:

// 1. 定義 action 的類型
type ActionType = { type: 'UPDATE_NAME'; payload: string }// 2. 為 action 指定類型為 ActionType
const reducer = (prevState: UserType, action: ActionType) => {console.log('觸發(fā)了 reducer 函數(shù)', action)// 3. 刪掉之前的代碼,再重復(fù)編寫這段邏輯的時(shí)候,會(huì)出現(xiàn) TS 的類型提示,非常 Niceswitch (action.type) {case 'UPDATE_NAME':return { ...prevState, name: action.payload }default:return prevState}
}

同時(shí),在 Father 組件的 onChangeName 處理函數(shù)內(nèi),調(diào)用 dispatch() 時(shí)也有了類型提示

const onChangeName = () => {dispatch({ type: 'UPDATE_NAME', payload: '劉龍彬' })
}

注意:在今后的開發(fā)中,正確的順序是

? 1、先定義 ActionType 的類型

? 2、修改 reducer 中的 switch...case... 邏輯

? 3、在組件中調(diào)用 dispatch() 函數(shù)!這樣能夠充分利用 TS 的類型提示。

6. 把用戶信息渲染到子組件中

1、在 Father 父組件中,通過jsx展開語(yǔ)法state 數(shù)據(jù)對(duì)象綁定為 Son1Son2props 屬性:

// 父組件
export const Father: React.FC = () => {const [state, dispatch] = useReducer(reducer, defaultState, initAction)const onChangeName = () => {dispatch({ type: 'UPDATE_NAME', payload: '劉龍彬' })}return (<div><button onClick={onChangeName}>修改 name 的值</button><div className="father"><!-- 通過 props 的數(shù)據(jù)綁定,把數(shù)據(jù)傳遞給子組件 --><Son1 {...state} /><Son2 {...state} /></div></div>)
}

2、在子組件中,指定 props 的類型為 React.FC<UserType>,并使用 props 接收和渲染數(shù)據(jù):

// 子組件1
const Son1: React.FC<UserType> = (props) => {return (<div className="son1"><p>用戶信息:</p><p>{JSON.stringify(props)}</p></div>)
}// 子組件2
const Son2: React.FC<UserType> = (props) => {return (<div className="son2"><p>用戶信息:</p><p>{JSON.stringify(props)}</p></div>)
}

修改完成后,點(diǎn)擊父組件中的 button 按鈕修改用戶名,我們發(fā)現(xiàn)兩個(gè)子組件中的數(shù)據(jù)同步發(fā)生了變化。

7. 在子組件中實(shí)現(xiàn)點(diǎn)擊按鈕 age 自增操作

1、擴(kuò)充 ActionType 的類型如下:

// 定義 action 的類型 
type ActionType = { type: 'UPDATE_NAME'; payload: string } | { type: 'INCREMENT'; payload: number }

2、在 reducer 中添加 INCREMENTcase 匹配:

const reducer = (prevState: UserType, action: ActionType) => {console.log('觸發(fā)了 reducer 函數(shù)', action)switch (action.type) {case 'UPDATE_NAME':return { ...prevState, name: action.payload }// 添加 INCREMENT 的 case 匹配case 'INCREMENT':return { ...prevState, age: prevState.age + action.payload }default:return prevState}
}

3、在子組件 Son1 中添加 +1button 按鈕,并綁定點(diǎn)擊事件處理函數(shù):

// 子組件1
const Son1: React.FC<UserType> = (props) => {const add = () => {}return (<div className="son1"><p>用戶信息:</p><p>{JSON.stringify(props)}</p><button onClick={add}>+1</button></div>)
}

4、現(xiàn)在的問題是:子組件 Son1 中無(wú)法調(diào)用到父組件的 dispatch 函數(shù)。

為了解決這個(gè)問題,我們需要在 Father 父組件中,通過 props 把父組件中的 dispatch 傳遞給子組件:

// 父組件
export const Father: React.FC = () => {// useReducer(fn, 初始數(shù)據(jù), 對(duì)初始數(shù)據(jù)進(jìn)行處理的fn)const [state, dispatch] = useReducer(reducer, defaultState, initAction)const onChangeName = () => {dispatch({ type: 'UPDATE_NAME', payload: '劉龍彬' })}return (<div><button onClick={onChangeName}>修改 name 的值</button><div className="father"><Son1 {...state} dispatch={dispatch} /><Son2 {...state} /></div></div>)
}

5、在 Son1 子組件中,擴(kuò)充 React.FC<UserType> 的類型,并從 props 中把 dispatch用戶信息對(duì)象分離出來:

// 子組件1
const Son1: React.FC<UserType & { dispatch: React.Dispatch<ActionType> }> = (props) => {const { dispatch, ...user } = propsconst add = () => dispatch({ type: 'INCREMENT', payload: 1 })return (<div className="son1"><p>用戶信息:</p><p>{JSON.stringify(user)}</p><button onClick={add}>+1</button></div>)
}

8. 在子組件中實(shí)現(xiàn)點(diǎn)擊按鈕 age 自減操作

擴(kuò)充 ActionType 的類型如下:

// 定義 action 的類型 
type ActionType = { type: 'UPDATE_NAME'; payload: string } | { type: 'INCREMENT'; payload: number } | { type: 'DECREMENT'; payload: number }

在 reducer 中添加 DECREMENT 的 case 匹配:

const reducer = (prevState: UserType, action: ActionType) => {console.log('觸發(fā)了 reducer 函數(shù)', action)switch (action.type) {case 'UPDATE_NAME':return { ...prevState, name: action.payload }case 'INCREMENT':return { ...prevState, age: prevState.age + action.payload }// 添加 DECREMENT 的 case 匹配case 'DECREMENT':return { ...prevState, age: prevState.age - action.payload }default:return prevState}
}

在子組件 Son2 中添加 -5 的 button 按鈕,并綁定點(diǎn)擊事件處理函數(shù):

// 子組件2
const Son2: React.FC<UserType> = (props) => {const sub = () => { }return (<div className="son2"><p>用戶信息:</p><p>{JSON.stringify(props)}</p><button onClick={sub}>-5</button></div>)
}

現(xiàn)在的問題是:子組件 Son2 中無(wú)法調(diào)用到父組件的 dispatch 函數(shù)。為了解決這個(gè)問題,我們需要在 Father 父組件中,通過 props 把父組件中的 dispatch 傳遞給子組件:

// 父組件
export const Father: React.FC = () => {// useReducer(fn, 初始數(shù)據(jù), 對(duì)初始數(shù)據(jù)進(jìn)行處理的fn)const [state, dispatch] = useReducer(reducer, defaultState, initAction)const onChangeName = () => {dispatch({ type: 'UPDATE_NAME', payload: '劉龍彬' })}return (<div><button onClick={onChangeName}>修改 name 的值</button><div className="father"><Son1 {...state} dispatch={dispatch} /><Son2 {...state} dispatch={dispatch} /></div></div>)
}

在 Son2 子組件中,擴(kuò)充 React.FC 的類型,并從 props 中把 dispatch用戶信息對(duì)象分離出來:

// 子組件2
const Son2: React.FC<UserType & { dispatch: React.Dispatch<ActionType> }> = (props) => {const { dispatch, ...user } = propsconst sub = () => dispatch({ type: 'DECREMENT', payload: 5 })return (<div className="son2"><p>用戶信息:</p><p>{JSON.stringify(user)}</p><button onClick={sub}>-5</button></div>)
}

9. 在 GrandSon 組件中實(shí)現(xiàn)重置按鈕

1、擴(kuò)充 ActionType 的類型如下:

// 定義 action 的類型 
type ActionType = { type: 'UPDATE_NAME'; payload: string } | { type: 'INCREMENT'; payload: number } | { type: 'DECREMENT'; payload: number } | { type: 'RESET' }

2、在 reducer 中添加 RESETcase 匹配:

const reducer = (prevState: UserType, action: ActionType) => {console.log('觸發(fā)了 reducer 函數(shù)', action)switch (action.type) {case 'UPDATE_NAME':return { ...prevState, name: action.payload }case 'INCREMENT':return { ...prevState, age: prevState.age + action.payload }case 'DECREMENT':return { ...prevState, age: prevState.age - action.payload }// 添加 RESET 的 case 匹配case 'RESET':return defaultStatedefault:return prevState}
}

3、在 GrandSon 組件中,添加重置按鈕,并綁定點(diǎn)擊事件處理函數(shù):

const GrandSon: React.FC<{ dispatch: React.Dispatch<ActionType> }> = (props) => {const reset = () => props.dispatch({ type: 'RESET' })return (<><h3>這是 GrandSon 組件</h3><button onClick={reset}>重置</button></>)
}

10. 使用 Immer 編寫更簡(jiǎn)潔的 reducer 更新邏輯

解決每次重新為 對(duì)象/數(shù)組 解除引用的問題

1、安裝 immer 相關(guān)的依賴包:

npm install immer use-immer -S

2、從 use-immer 中導(dǎo)入 useImmerReducer 函數(shù),并替換掉 React 官方的 useReducer 函數(shù)的調(diào)用:

// 1. 導(dǎo)入 useImmerReducer
import { useImmerReducer } from 'use-immer'// 父組件
export const Father: React.FC = () => {// 2. 把 useReducer() 的調(diào)用替換成 useImmerReducer()const [state, dispatch] = useImmerReducer(reducer, defaultState, initAction)
}

3、修改 reducer 函數(shù)中的業(yè)務(wù)邏輯,case 代碼塊中不再需要 return 不可變的新對(duì)象了,只需要在 prevState 上進(jìn)行修改即可。

Immer 內(nèi)部會(huì)復(fù)制并返回新對(duì)象,因此降低了用戶的心智負(fù)擔(dān)。改造后的 reducer 代碼如下:

const reducer = (prevState: UserType, action: ActionType) => {console.log('觸發(fā)了 reducer 函數(shù)', action)switch (action.type) {case 'UPDATE_NAME':// return { ...prevState, name: action.payload }prevState.name = action.payloadbreakcase 'INCREMENT':// return { ...prevState, age: prevState.age + action.payload }prevState.age += action.payloadbreakcase 'DECREMENT':// return { ...prevState, age: prevState.age - action.payload }prevState.age -= action.payloadbreakcase 'RESET':return defaultStatedefault:return prevState}
}
http://www.risenshineclean.com/news/60687.html

相關(guān)文章:

  • 開設(shè)公司網(wǎng)站愛站關(guān)鍵詞
  • 百度網(wǎng)站如何做網(wǎng)絡(luò)營(yíng)銷的方式
  • 建個(gè)網(wǎng)站費(fèi)用微信管理系統(tǒng)軟件
  • 閘北區(qū)網(wǎng)站設(shè)計(jì)與制優(yōu)化推廣網(wǎng)站怎么做最好
  • 網(wǎng)站投訴平臺(tái)公眾號(hào)軟文素材
  • 學(xué)做餅干網(wǎng)站全球網(wǎng)站流量排名100
  • 揚(yáng)州做網(wǎng)站需要多少錢搜索引擎優(yōu)化需要多少錢
  • 網(wǎng)頁(yè)設(shè)計(jì)與制作建立站點(diǎn)實(shí)踐報(bào)告怎么開發(fā)一個(gè)網(wǎng)站
  • 做百度移動(dòng)端網(wǎng)站營(yíng)銷服務(wù)機(jī)構(gòu)
  • 網(wǎng)站有哪些后臺(tái)寧波seo優(yōu)化
  • 合肥怎么做網(wǎng)站高平網(wǎng)站優(yōu)化公司
  • 網(wǎng)站改版會(huì)影響排名嗎營(yíng)銷方法
  • 濟(jì)南建設(shè)網(wǎng)站阿里巴巴國(guó)際站運(yùn)營(yíng)
  • 成都網(wǎng)站建設(shè)公司興田德潤(rùn)在哪兒個(gè)人發(fā)布信息的免費(fèi)平臺(tái)
  • wordpress雙域名重慶網(wǎng)站排名優(yōu)化教程
  • 泉州做網(wǎng)站優(yōu)化公司建站模板哪個(gè)好
  • wordpress 彩色標(biāo)簽云 插件windows優(yōu)化大師電腦版
  • 做網(wǎng)站運(yùn)營(yíng)有前景嗎愛站長(zhǎng)尾詞
  • wordpress創(chuàng)建子目錄win7一鍵優(yōu)化工具
  • 美國(guó)哪個(gè)網(wǎng)站做diy電腦版怎么建立公司網(wǎng)站
  • 商城類網(wǎng)站建設(shè) 數(shù)據(jù)庫(kù)推廣賺錢一個(gè)2元
  • 貴陽(yáng)做網(wǎng)站 優(yōu)幫云產(chǎn)品推廣計(jì)劃書怎么寫
  • 南昌專業(yè)做網(wǎng)站公司seminar是什么意思
  • 中關(guān)村在線官方網(wǎng)站電腦培訓(xùn)機(jī)構(gòu)哪家最好
  • 門戶網(wǎng)站建設(shè)意義甲馬營(yíng)seo網(wǎng)站優(yōu)化的
  • 如何做國(guó)外網(wǎng)站彩票的推廣培訓(xùn)機(jī)構(gòu)
  • 從江網(wǎng)站建設(shè)公司的公關(guān)
  • 深圳企業(yè)網(wǎng)站推廣網(wǎng)址大全qq瀏覽器
  • 自建淘寶客APP網(wǎng)站模板網(wǎng)絡(luò)推廣服務(wù)外包公司
  • 外貿(mào)門戶網(wǎng)站如何創(chuàng)建自己的域名