当前位置: 首页 > news >正文

可以做图片视频的网站深圳网络设计

可以做图片视频的网站,深圳网络设计,wordpress文章保存图片不显示,商业网站缩写useReducer usereducer 相当于 复杂的 useState 当状态更新逻辑较复杂时可以考虑使用 useReducer。useReducer 可以同时更新多个状态#xff0c;而且能把对状态的修改从组件中独立出来。 相比于 useState#xff0c;useReducer 可以更好的描述“如何更新状态”。例如#…useReducer usereducer 相当于 复杂的 useState 当状态更新逻辑较复杂时可以考虑使用 useReducer。useReducer 可以同时更新多个状态而且能把对状态的修改从组件中独立出来。 相比于 useStateuseReducer 可以更好的描述“如何更新状态”。例如组件负责发出行为useReducer 负责更新状态。 好处是让代码逻辑更清晰代码行为更易预测。 1. useReducer 的语法格式 useReducer 的基础语法如下 const [state, dispatch] useReducer(reducer, initState, initAction?)其中 1. reducer 是一个函数类似于 (prevState, action) newState。形参 prevState 表示旧状态形参 action 表示本次的行为返回值 newState 表示处理完毕后的新状态。 2. initState 表示初始状态也就是默认值。 3. initAction 是进行状态初始化时候的处理函数它是可选的如果提供了 initAction 函数则会把 initState 传递给 initAction 函数进行处理initAction 的返回值会被当做初始状态。 4. 返回值 state 是状态值。dispatch 是更新 state 的方法让他接收 action 作为参数useReducer 只需要调用 dispatch(action) 方法传入的 action 即可更新 state。 2. 定义组件的基础结构 定义名为 Father 的父组件如下 import React from react// 父组件 export const Father: React.FC () {return (divbutton修改 name 的值/buttondiv classNamefatherSon1 /Son2 //div/div) }定义名为 Son1 和 Son2 的两个子组件如下 // 子组件1 const Son1: React.FC () {return div classNameson1/div }// 子组件2 const Son2: React.FC () {return div classNameson2/div }在 index.css 中添加对应的样式 .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 的基础结构 1、按需导入 useReducer 函数 import React, { useReducer } from react2、定义初始数据 const defaultState { name: liulongbin, age: 16 }3、定义 reducer 函数它的作用是根据旧状态进行一系列处理最终返回新状态 // 第一个参数永远是上一次的旧状态 const reducer (prevState) {// 首次进入页面 不会触发 reducer 函数执行console.log(触发了 reducer 函数)// 必须向外返回一个处理好的新状态 return prevState }4、在 Father 组件中调用 useReducer(reducerFn, 初始状态) 函数并得到 reducer 返回的状态 // 父组件 export const Father: React.FC () {// useReducer(fn, 初始数据, 对初始数据进行处理的fn)const [state] useReducer(reducer, defaultState)console.log(state)return (divbutton修改 name 的值/buttondiv classNamefatherSon1 /Son2 //div/div) }5、为 reducer 中的 initState 指定数据类型 // 定义状态的数据类型 type UserType typeof defaultStateconst defaultState { name: liulongbin, age: 16 }// 给 initState 指定类型为 UserType const reducer (prevState: UserType) {console.log(触发了 reducer 函数)return prevState }6、接下来在 Father 组件中使用 state 时就可以出现类型的智能提示啦 // 父组件 export const Father: React.FC () {const [state] useReducer(reducer, defaultState)console.log(state.name, state.age)return (divbutton修改 name 的值/buttondiv classNamefatherSon1 /Son2 //div/div) }4. 使用 initAction 处理初始数据 定义名为 initAction 的处理函数如果初始数据中的 age 为小数、负数、或 0 时对 age 进行非法值的处理 const initAction (initState: UserType) {// 把 return 的对象作为 useReducer 的初始值return { ...initState, age: Math.round(Math.abs(initState.age)) || 18 } }在 Father 组件中使用步骤1声明的 initAction 函数如下 // 父组件 export const Father: React.FC () {// useReducer(fn, 初始数据, 对初始数据进行处理的fn)const [state] useReducer(reducer, defaultState, initAction)// 省略其它代码... }在定义 defaultState 时为 age 提供非法值可以看到非法值在 initAction 中被处理掉了。 5. 在 Father 组件中点击按钮修改 name 的值 1. 错误示范 不要像 vue 响应式数据一样直接通过 state.name escook 去修改 // 父组件 export const Father: React.FC () {// useReducer(fn, 初始数据, 对初始数据进行处理的fn)const [state] useReducer(reducer, defaultState, initAction)console.log(state)const onChangeName () {// 注意这种用法是错误的因为不能【直接修改 state 的值】// 因为存储在 useReducer 中的数据都是“不可变”的// 要想修改 useReducer 中的数据必须触发 【reducer】 函数的重新计算// 根据 reducer 形参中的旧状态对象initState经过一系列处理返回一个“全新的”状态对象state.name escook}return (divbutton onClick{onChangeName}修改 name 的值/buttondiv classNamefatherSon1 /Son2 //div/div) }2. 正确的操作 为了能够触发 reducer 函数的重新执行我们需要在调用 useReducer() 后接收返回的 dispatch 函数。示例代码如下 // Father 父组件 const [state, dispatch] useReducer(reducer, defaultState, initAction)在 button 按钮的点击事件处理函数中调用 dispatch() 函数从而触发 reducer 函数的重新计算 // Father 父组件 const onChangeName () { dispatch() }点击 Father 组件中如下的 button 按钮 button onClick{onChangeName}修改 name 的值/button会触发 reducer 函数的重新执行并打印 reducer 中的 console.log()代码如下 const reducer (prevState: UserType) {console.log(触发了 reducer 函数)return prevState }3. 调用 dispatch 传递参数给 reducer 在 Father 父组件按钮的点击事件处理函数 onChangeName 中调用 dispatch() 函数并把参数传递给 reducer 的第2个形参代码如下 const onChangeName () {// 注意参数的格式为 { type, payload? }// 其中// type 的值是一个唯一的标识符用来【指定本次操作的类型】一般为大写的字符串// payload 是本次操作需要用到的数据为可选参数。在这里payload 指的是把用户名改为字符串 刘龙彬dispatch({type: UPDATE_NAME, payload: 刘龙彬}) }修改 reducer 函数的形参添加名为 action 的第2个形参用来接收 dispatch 传递过来的数据 const reducer (prevState: UserType, action) {// 打印 action 的值终端显示的值为// {type: UPDATE_NAME, payload: 刘龙彬}console.log(触发了 reducer 函数, action)return prevState }在 reducer 中根据接收到的 action.type 标识符决定进行怎样的更新操作最终 return 一个计算好的新状态。示例代码如下 const reducer (prevState: UserType, action) {console.log(触发了 reducer 函数, action)// return prevStateswitch (action.type) {// 如果标识符是字符串 UPDATE_NAME则把用户名更新成 action.payload 的值// 最后一定要返回一个新状态因为 useReducer 中每一次的状态都是“不可变的”case UPDATE_NAME:return { ...prevState, name: action.payload } // 解除引用赋予新对象// 兜底操作// 如果没有匹配到任何操作则默认返回上一次的旧状态default:return prevState} }4、为 action 指定类型 在上述的 switch...case... 代码期间没有 TS 的类型提示这在大型项目中是致命的。因此我们需要为 reducer 函数的第2个形参 action 指定操作的类型 // 1. 定义 action 的类型 type ActionType { type: UPDATE_NAME; payload: string }// 2. 为 action 指定类型为 ActionType const reducer (prevState: UserType, action: ActionType) {console.log(触发了 reducer 函数, action)// 3. 删掉之前的代码再重复编写这段逻辑的时候会出现 TS 的类型提示非常 Niceswitch (action.type) {case UPDATE_NAME:return { ...prevState, name: action.payload }default:return prevState} }同时在 Father 组件的 onChangeName 处理函数内调用 dispatch() 时也有了类型提示 const onChangeName () {dispatch({ type: UPDATE_NAME, payload: 刘龙彬 }) }注意在今后的开发中正确的顺序是 ​ 1、先定义 ActionType 的类型 ​ 2、修改 reducer 中的 switch...case... 逻辑 ​ 3、在组件中调用 dispatch() 函数这样能够充分利用 TS 的类型提示。 6. 把用户信息渲染到子组件中 1、在 Father 父组件中通过jsx展开语法把 state 数据对象绑定为 Son1 和 Son2 的 props 属性 // 父组件 export const Father: React.FC () {const [state, dispatch] useReducer(reducer, defaultState, initAction)const onChangeName () {dispatch({ type: UPDATE_NAME, payload: 刘龙彬 })}return (divbutton onClick{onChangeName}修改 name 的值/buttondiv classNamefather!-- 通过 props 的数据绑定把数据传递给子组件 --Son1 {...state} /Son2 {...state} //div/div) }2、在子组件中指定 props 的类型为 React.FCUserType并使用 props 接收和渲染数据 // 子组件1 const Son1: React.FCUserType (props) {return (div classNameson1p用户信息/pp{JSON.stringify(props)}/p/div) }// 子组件2 const Son2: React.FCUserType (props) {return (div classNameson2p用户信息/pp{JSON.stringify(props)}/p/div) }修改完成后点击父组件中的 button 按钮修改用户名我们发现两个子组件中的数据同步发生了变化。 7. 在子组件中实现点击按钮 age 自增操作 1、扩充 ActionType 的类型如下 // 定义 action 的类型 type ActionType { type: UPDATE_NAME; payload: string } | { type: INCREMENT; payload: number }2、在 reducer 中添加 INCREMENT 的 case 匹配 const reducer (prevState: UserType, action: ActionType) {console.log(触发了 reducer 函数, 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 中添加 1 的 button 按钮并绑定点击事件处理函数 // 子组件1 const Son1: React.FCUserType (props) {const add () {}return (div classNameson1p用户信息/pp{JSON.stringify(props)}/pbutton onClick{add}1/button/div) }4、现在的问题是子组件 Son1 中无法调用到父组件的 dispatch 函数。 为了解决这个问题我们需要在 Father 父组件中通过 props 把父组件中的 dispatch 传递给子组件 // 父组件 export const Father: React.FC () {// useReducer(fn, 初始数据, 对初始数据进行处理的fn)const [state, dispatch] useReducer(reducer, defaultState, initAction)const onChangeName () {dispatch({ type: UPDATE_NAME, payload: 刘龙彬 })}return (divbutton onClick{onChangeName}修改 name 的值/buttondiv classNamefatherSon1 {...state} dispatch{dispatch} /Son2 {...state} //div/div) }5、在 Son1 子组件中扩充 React.FCUserType 的类型并从 props 中把 dispatch 和用户信息对象分离出来 // 子组件1 const Son1: React.FCUserType { dispatch: React.DispatchActionType } (props) {const { dispatch, ...user } propsconst add () dispatch({ type: INCREMENT, payload: 1 })return (div classNameson1p用户信息/pp{JSON.stringify(user)}/pbutton onClick{add}1/button/div) }8. 在子组件中实现点击按钮 age 自减操作 扩充 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(触发了 reducer 函数, 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 按钮并绑定点击事件处理函数 // 子组件2 const Son2: React.FCUserType (props) {const sub () { }return (div classNameson2p用户信息/pp{JSON.stringify(props)}/pbutton onClick{sub}-5/button/div) }现在的问题是子组件 Son2 中无法调用到父组件的 dispatch 函数。为了解决这个问题我们需要在 Father 父组件中通过 props 把父组件中的 dispatch 传递给子组件 // 父组件 export const Father: React.FC () {// useReducer(fn, 初始数据, 对初始数据进行处理的fn)const [state, dispatch] useReducer(reducer, defaultState, initAction)const onChangeName () {dispatch({ type: UPDATE_NAME, payload: 刘龙彬 })}return (divbutton onClick{onChangeName}修改 name 的值/buttondiv classNamefatherSon1 {...state} dispatch{dispatch} /Son2 {...state} dispatch{dispatch} //div/div) }在 Son2 子组件中扩充 React.FC 的类型并从 props 中把 dispatch 和用户信息对象分离出来 // 子组件2 const Son2: React.FCUserType { dispatch: React.DispatchActionType } (props) {const { dispatch, ...user } propsconst sub () dispatch({ type: DECREMENT, payload: 5 })return (div classNameson2p用户信息/pp{JSON.stringify(user)}/pbutton onClick{sub}-5/button/div) }9. 在 GrandSon 组件中实现重置按钮 1、扩充 ActionType 的类型如下 // 定义 action 的类型 type ActionType { type: UPDATE_NAME; payload: string } | { type: INCREMENT; payload: number } | { type: DECREMENT; payload: number } | { type: RESET }2、在 reducer 中添加 RESET 的 case 匹配 const reducer (prevState: UserType, action: ActionType) {console.log(触发了 reducer 函数, 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 组件中添加重置按钮并绑定点击事件处理函数 const GrandSon: React.FC{ dispatch: React.DispatchActionType } (props) {const reset () props.dispatch({ type: RESET })return (h3这是 GrandSon 组件/h3button onClick{reset}重置/button/) }10. 使用 Immer 编写更简洁的 reducer 更新逻辑 解决每次重新为 对象/数组 解除引用的问题 1、安装 immer 相关的依赖包 npm install immer use-immer -S2、从 use-immer 中导入 useImmerReducer 函数并替换掉 React 官方的 useReducer 函数的调用 // 1. 导入 useImmerReducer import { useImmerReducer } from use-immer// 父组件 export const Father: React.FC () {// 2. 把 useReducer() 的调用替换成 useImmerReducer()const [state, dispatch] useImmerReducer(reducer, defaultState, initAction) }3、修改 reducer 函数中的业务逻辑case 代码块中不再需要 return 不可变的新对象了只需要在 prevState 上进行修改即可。 Immer 内部会复制并返回新对象因此降低了用户的心智负担。改造后的 reducer 代码如下 const reducer (prevState: UserType, action: ActionType) {console.log(触发了 reducer 函数, 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.laogonggong.com/news/124319.html

相关文章:

  • xx企业网站建设方案书企业宣传报道模板范文
  • 东莞建网站哪家好福建seo排名
  • 成都微信公众号外包google seo优化
  • 怎样开物流网站商城网站备案需要什么
  • 网站建设服务英文深圳市建设工程服务交易中心
  • 南宁本地有几家网站开发郑州做网站哪个平台好
  • 宁波公司建设网站网站开发与维护工资
  • 做卖东西的网站多少钱杭州建德网站建设
  • 个人网站作品欣赏餐饮营销方案100例
  • 长春专业做网站的公司为什么有人做商城优惠券网站卖
  • 全面的锦州网站建设wordpress分类目录发不了文章
  • 晋江市建设局网站网站首页如何做浮动窗口
  • 济南网站建设vashine苏州建设职业培训中心官网
  • 东莞响应式网站建设定制wordpress博客分页
  • 注册 网站开发 公司数据库修改网站管理员密码
  • 如何做自助网站建立企业网站流程
  • 网站建设台州百度手机助手下载安卓
  • 郑州锐途网站建设湖北住房城乡建设厅网站
  • ps网站首页直线教程wordpress面包屑导航代码
  • 做gif表情包的网站wordpress 类似的平台
  • 网站建设一次哪些企业会考虑做网站
  • 企业怎么建设自己的网站黄金路网站建设公司
  • asp.net网站支持多国语言wordpress上传附件到FTP
  • 网站备案怎么这么麻烦百度投流运营
  • 网站建设费科目彩票网站html模板
  • 辽宁网站推广的目的推荐几个的网站
  • 网站销售源码哪些网站是做免费推广的
  • 企业开办网站wordpress淘宝客自动采集器
  • 西安汇友网站建设不会写代码如何做网站
  • 网站的互动功能wordpress 静态资源加速